/**
 @file sys_usw_linkagg.c

 @date 2009-10-19

 @version v2.0

 The file contains all Linkagg APIs of sys layer
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_debug.h"
#include "ctc_error.h"

#include "sys_usw_common.h"
#include "sys_usw_linkagg.h"
#include "sys_usw_port_api.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_register.h"
#include "sys_usw_opf.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_dmps.h"
#include "sys_usw_learning_aging.h"
#include "sys_usw_ftm.h"
#include "sys_usw_dma.h"

#include "drv_api.h"

/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
struct sys_linkagg_mem_s
{
    uint16  tid;                /**< linkAggId */
    uint16  mem_valid_num;      /**< member num of linkAgg group */
    uint8  linkagg_mode;       /**< ctc_linkagg_group_mode_t */
    uint8  need_pad;

    uint16  port_cnt;          /* member num of linkAgg group */
    uint8  ref_cnt;           /*for bpe cb cascade*/
    uint32 gport;             /**< member port */

    uint16  port_index;
};
typedef struct sys_linkagg_mem_s sys_linkagg_mem_t;

struct sys_linkagg_stats_s
{
    uint8 lchip;
    uint32 total_group_cnt;
    uint32 total_member_cnt;
    uint32 static_group_cnt;
    uint32 static_group_lmpf_cnt;
    uint32 static_group_spm_cnt;
    uint32 static_group_spm_flow_cnt;
    uint32 static_member_cnt;
    uint32 failover_group_cnt;
    uint32 failover_group_lmpf_cnt;
    uint32 failover_member_cnt;
    uint32 rr_group_cnt;
    uint32 rr_group_random_cnt;
    uint32 rr_member_cnt;
    uint32 dynamic_group_cnt;
    uint32 dynamic_member_cnt;
};
typedef struct sys_linkagg_stats_s sys_linkagg_stats_t;


enum sys_linkagg_replace_e
{
    SYS_LAG_REP_FIXED_MEM  =  0x00000001,
    SYS_LAG_REP_MEM_LAG  =  0x00000002
};

/* dynamic interval */

#define SYS_LINKAGG_GOTO_ERROR(ret, error_proc) \
    do { \
        if (ret < 0) \
        {\
            goto error_proc;\
        } \
       } while (0)

#define SYS_LINKAGG_LOCK_INIT() \
    do { \
        int32 ret = sal_mutex_create(&(p_usw_linkagg_master[lchip]->p_linkagg_mutex)); \
        if (ret || !(p_usw_linkagg_master[lchip]->p_linkagg_mutex)) \
        { \
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Create linkagg mutex fail!\n"); \
            mem_free(p_usw_linkagg_master[lchip]); \
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Create mutex fail\n");\
            return CTC_E_NO_MEMORY;\
 \
        } \
    } while (0)

#define SYS_TID_VALID_CHECK(tid) \
    if (tid >= MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM)){\
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");\
        return CTC_E_BADID;\
 }

 #define SYS_MEM_NUM_VALID_CHECK(mem_num) \
    if (mem_num > MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM)){\
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member of linkagg group reach Max, add member port fail!\n");\
        return CTC_E_INVALID_PARAM;\
 }

#define LINKAGG_LOCK \
    if (p_usw_linkagg_master[lchip]->p_linkagg_mutex) sal_mutex_lock(p_usw_linkagg_master[lchip]->p_linkagg_mutex)
#define LINKAGG_UNLOCK \
    if (p_usw_linkagg_master[lchip]->p_linkagg_mutex) sal_mutex_unlock(p_usw_linkagg_master[lchip]->p_linkagg_mutex)

#define SYS_LINKAGG_GET_GROUP_MEMBER_NUM(tid, mem_num) \
    if(p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_56) \
    { \
        (DRV_IS_DUET2(lchip)) ? (mem_num = (tid > MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_TID_MAX)) ? 16 : 32) : \
        (mem_num = (tid > MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_TID_MAX)) ? 32 : 64); \
    } \
    else \
    { \
        uint8 linkagg_num = (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_4)? 4:\
                            ((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_8)? 8:\
                            ((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_16)? 16:\
                            ((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_32)? 32: 64)));\
        mem_num =  MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM) / linkagg_num; \
    }

#define SYS_LINKAGG_GET_GROUP_MEMBER_BASE(tid, mem_num, mem_base) \
    if((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_56) && (tid > MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_TID_MAX))) \
    { \
        mem_base =  MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_MEM_MAX) + (tid - MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_TID_MAX) -1) * mem_num; \
    } \
    else \
    { \
        mem_base = tid * mem_num; \
    }

#define SYS_LINKAGG_GET_GROUP_DLB_FLOW_NUM(tid, flow_num) \
    if(p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_56) \
    { \
        flow_num = MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM) / (MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_TID_MAX) + 1); \
    } \
    else \
    { \
        uint8 linkagg_num = (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_4)? 4:\
                            ((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_8)? 8:\
                            ((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_16)? 16:\
                            ((p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_32)? 32: 64)));\
        flow_num = MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM) / linkagg_num; \
    }

#define SYS_LINKAGG_GET_GROUP_DLB_FLOW_BASE(tid, flow_num, mem_base) \
    do{ \
        mem_base = tid * flow_num; \
    }while(0)

#define SYS_LINKAGG_MAP_GPORT_TO_GCHIP_LPORT(gport) ((CTC_MAP_GPORT_TO_GCHIP(gport) << (CTC_LOCAL_PORT_LENGTH + CTC_EXT_PORT_LENGTH)) | CTC_MAP_GPORT_TO_LPORT(gport))

STATIC int32
_sys_usw_linkagg_add_port_hw(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 replace);
STATIC bool
_sys_usw_linkagg_port_is_member(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint16* index, uint16* hw_index);
STATIC int32
_sys_usw_linkagg_set_channel_property(uint8 lchip, uint8 tid, uint32 value);

int32
_sys_usw_linkagg_remove_port_hw(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 replace);

extern int32
_sys_usw_linkagg_wb_init(uint8 lchip);

extern int32
sys_usw_l2_set_dsmac(uint8 lchip, uint32 gport, bool b_add);

extern int32
sys_usw_parser_set_linkagg_hash_field(uint8 lchip, ctc_parser_linkagg_hash_ctl_t* p_hash_ctl);

extern int32
sys_usw_parser_get_linkagg_hash_field(uint8 lchip, ctc_parser_linkagg_hash_ctl_t* p_hash_ctl);

extern int32
sys_usw_linkagg_wb_sync(uint8 lchip,uint32 app_id);

extern int32
sys_usw_linkagg_wb_restore(uint8 lchip);

extern int32
sys_usw_linkagg_dump_db(uint8 lchip, sal_file_t dump_db_fp, ctc_global_dump_db_t* p_dump_param);

extern int32
_sys_usw_linkagg_get_ports2(uint8 lchip, sys_linkagg_t* p_group, uint32* member_list, uint8* p_member_cnt);

extern int32
_sys_at_linkagg_get_profile_by_speed_mode(uint8 lchip, uint32 gport, uint32 *value);

sys_linkagg_master_t* p_usw_linkagg_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/
#define __HW_SYNC__
STATIC int32
_sys_usw_hw_sync_add_member(uint8 lchip, uint16 tid, uint32 gport)
{
    uint32 cmd = 0;
    DsLinkAggregateChannel_m linkagg_channel;
    uint32 channel_id = 0;
    uint32 value = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x gport =  %d \n", tid, gport);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
    channel_id = SYS_USW_CHANNEL_ENCODE(channel_id);
    cmd = DRV_IOR(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));
    value = tid;
    SetDsLinkAggregateChannel(V, u1_g1_linkAggregationGroup_f, &linkagg_channel, value);
    SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 0);
    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_hw_sync_del_member(uint8 lchip, uint16 tid, uint32 gport)
{
    uint32 cmd = 0;
    DsLinkAggregateChannel_m linkagg_channel;
    uint32 channel_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x gport =  %d \n", tid, gport);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
    channel_id = SYS_USW_CHANNEL_ENCODE(channel_id);
    cmd = DRV_IOR(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));
    SetDsLinkAggregateChannel(V, u1_g1_linkAggregationGroup_f, &linkagg_channel, 0);
    SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 0);
    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

int32
sys_usw_linkagg_failover_isr(uint8 lchip, uint32 intr, void* p_data)
{
    uint32 cmd = 0;
    LinkAggScanLinkDownChanRecord_m chan_down;
    DsLinkAggregateChannel_m linkagg_channel;
    uint16 index = 0;
    uint8 linkdown_chan = 0;
    sys_intr_type_t type;
    uint32 link_state[4] = {0};
    uint16 lport = 0;
    uint8  gchip = 0;
    uint32 gport = 0;
    uint8  tid = 0;
    sys_linkagg_t* p_group = NULL;

    SYS_LINKAGG_INIT_CHECK();
    if (sys_usw_chip_get_reset_hw_en(lchip))
    {
        return CTC_E_NONE;
    }
    sal_memset(&type, 0, sizeof(sys_intr_type_t));
    type.intr = SYS_INTR_FUNC_CHAN_LINKDOWN_SCAN;
    type.sub_intr = INVG;

    /* mask linkdown interrupt */
    sys_usw_interrupt_set_en(lchip, &type, FALSE);

    sal_memset(&chan_down, 0, sizeof(chan_down));
    cmd = DRV_IOR(LinkAggScanLinkDownChanRecord_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &chan_down));
    GetLinkAggScanLinkDownChanRecord(A, linkDownScanChanRecord_f, &chan_down, &(link_state[0]));
    cmd = DRV_IOW(LinkAggScanLinkDownChanRecord_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &chan_down));

    for (index = 0; index < 64; index++)
    {
        if ((link_state[index/32] >>(index%32)) & 0x1)
        {
            linkdown_chan = index;
            /*normal trunk*/
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "chan_down:0x%x\n ", linkdown_chan);
            cmd = DRV_IOR(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, linkdown_chan, cmd, &linkagg_channel));
            tid = GetDsLinkAggregateChannel(V, u1_g1_linkAggregationGroup_f, &linkagg_channel);
            p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
            if (p_group)
            {
                lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, linkdown_chan);
                CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
                gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);
                SYS_MAX_PHY_PORT_CHECK(gport);
                _sys_usw_linkagg_remove_port_to_db(lchip, p_group, gport);
                if (!p_usw_linkagg_master[lchip]->bind_gport_disable)
                {
                    sys_usw_port_api_set_global_port(lchip, lport, gport, TRUE);
                }
            }
        }
    }

    /* release linkdown interrupt */
    sys_usw_interrupt_set_en(lchip, &type, TRUE);

    return CTC_E_NONE;
}

#define __fragment_move__
/*
typedef int32 (* vector_traversal_fn)(void* array_data, void* user_data);
typedef void (* ctc_list_del_cb_t) (void* val);
typedef int32 (* ctc_list_cmp_cb_t) (void* val1, void* val2);
*/
STATIC int32 _sys_usw_linkagg_linklist_cmp(sys_linkagg_t* val1, sys_linkagg_t* val2)
{
    if(val1->member_base < val2->member_base)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}

STATIC int32 _sys_usw_linkagg_fragment_traverse(sys_linkagg_t* val, void* user_data)
{
    sys_traverse_t* p_param = user_data;
    ctc_linklist_t* p_member_list = (ctc_linklist_t*)(p_param->data);
    uint8 lchip = p_param->value1;
    if(DRV_FROM_TMM(lchip) && val->mode == CTC_LINKAGG_MODE_DLB)
    {
        return CTC_E_NONE;
    }
    ctc_listnode_add_sort(p_member_list, val);
    return CTC_E_NONE;
}

int32 _sys_usw_linkagg_fragment(uint8 lchip)
{
    int32  ret = CTC_E_NONE;
    int32  free_length;
    uint8  find;
    sys_traverse_t param;
    sys_usw_opf_t opf;
    sys_linkagg_t   head_group;
    sys_linkagg_t* first_group = NULL;
    sys_linkagg_t* next_group = NULL;
    sys_linkagg_t* find_group = NULL;
    ctc_listnode_t* f_node;
    ctc_listnode_t* node;
    ctc_linklist_t* p_member_list = ctc_list_create((ctc_list_cmp_cb_t)_sys_usw_linkagg_linklist_cmp, NULL);

    if(!p_member_list)
    {
    	return CTC_E_NO_MEMORY;
    }

    if(p_usw_linkagg_master[lchip]->linkagg_mode != CTC_LINKAGG_MODE_FLEX)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Only flexiable mode support fragment\n");
        ret = CTC_E_NOT_SUPPORT;
        goto error_proc;
    }

    sal_memset(&opf, 0, sizeof(opf));
    sal_memset(&head_group, 0, sizeof(head_group));
    sal_memset(&param, 0, sizeof(param));

    ctc_listnode_add_sort(p_member_list, &head_group);
     /* vector raverse;*/
    param.data = p_member_list;
    param.value1 = lchip;
    CTC_ERROR_GOTO(ctc_vector_traverse(p_usw_linkagg_master[lchip]->group_vector,
                                (vector_traversal_fn)_sys_usw_linkagg_fragment_traverse, &param), ret, error_proc);

    for(f_node = p_member_list->head; f_node && f_node->next; f_node = f_node->next)
    {
        next_group = (sys_linkagg_t*)f_node->next->data;
        first_group = f_node->data;

        free_length = next_group->member_base - first_group->member_base - first_group->max_member_num;

        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "first group info:\n");
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "      %10s: %-10d\n","tid", first_group->tid);
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "      %10s: %-10d\n","max member num", first_group->max_member_num);
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "      %10s: %-10d\n","member base", first_group->member_base);

        if(free_length == 0)
        {
            continue;
        }
        else if(free_length < 0)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg fragment error!\n");
            ret =  CTC_E_INVALID_PARAM;
            goto error_proc;
        }

        while(1)
        {
             /*double check for while*/
            if(free_length <= 0)
            {
                break;
            }

            find = 0;
            for(node = p_member_list->tail; node; node=node->prev)
            {
                if(node == f_node)
                {
                    break;
                }

                find_group = (sys_linkagg_t*)node->data;

                if((find_group->mode != CTC_LINKAGG_MODE_DLB) && (find_group->mode != CTC_LINKAGG_MODE_STATIC_FAILOVER) &&
                    (find_group->max_member_num == free_length) && (find_group->member_base > first_group->member_base))
                {
                    find = 1;
                    break;
                }
            }

            if(find)
            {
                 /* first update  hardware*/
                uint16 mem_idx;
                DsLinkAggregateMember_m member;
                DsLinkAggregateGroup_m  group;
                uint16 new_member_base = first_group->member_base + first_group->max_member_num;
                uint32 cmdr = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
                uint32 cmdw = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);

                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "The find group info:\n");
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "      %10s: %-10d\n","tid", find_group->tid);
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "      %10s: %-10d\n","max member num", find_group->max_member_num);
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "      %10s: %-10d\n","member base", find_group->member_base);

                for(mem_idx=0; mem_idx < find_group->max_member_num; mem_idx++)
                {
                    CTC_ERROR_GOTO(DRV_IOCTL(lchip, find_group->member_base+mem_idx, cmdr, &member), ret, error_proc);
                    CTC_ERROR_GOTO(DRV_IOCTL(lchip, new_member_base+mem_idx, cmdw, &member), ret, error_proc);
                }

                cmdr = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
                cmdw = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);

                CTC_ERROR_GOTO(DRV_IOCTL(lchip, find_group->tid, cmdr, &group), ret, error_proc);
                SetDsLinkAggregateGroup(V, linkAggMemBase_f, &group, new_member_base);
                CTC_ERROR_GOTO(DRV_IOCTL(lchip, find_group->tid, cmdw, &group), ret, error_proc);

                opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;
                opf.pool_index = 0;
                CTC_ERROR_GOTO(sys_usw_opf_free_offset(lchip, &opf, find_group->max_member_num,
                                                                        find_group->member_base), ret, error_proc);

                CTC_ERROR_GOTO(sys_usw_opf_alloc_offset_from_position(lchip, &opf, find_group->max_member_num,
                                                                        new_member_base), ret, error_proc);

                find_group->member_base = new_member_base;
                ctc_listnode_delete_node(p_member_list, node);
                ctc_listnode_add_sort(p_member_list, find_group);
                break;
            }
            else
            {
                free_length -= MCHIP_CAP(SYS_CAP_LINKAGG_FRAGMENT_SIZE);
            }
    	}
    }

 error_proc:
    ctc_list_delete(p_member_list);
    return ret;
}

#define __DLB__
uint32
_sys_usw_linkagg_driver2flows(uint8 lchip, uint8 driver_value, uint8 is_spm)
{
    uint32 flow_num = 0;

    if(is_spm)
    {
        flow_num = MCHIP_CAP(SYS_CAP_LINKAGG_SPM_FLOW_NUM_GRAN) * (1 << driver_value);
    }
    else
    {
        if (DRV_IS_DUET2(lchip))
        {
            flow_num = 256 / (1 << driver_value);
        }
        else
        {
            flow_num = 16 * (1 << driver_value);
        }
    }

    return flow_num;
}
STATIC uint32
_sys_usw_linkagg_flows2driver(uint8 lchip, uint32 num_flow, uint8 is_spm)
{
    uint32 driver_value = 0;

    if(is_spm)
    {
        num_flow = num_flow / MCHIP_CAP(SYS_CAP_LINKAGG_SPM_FLOW_NUM_GRAN) * 16;
    }

    if(DRV_IS_DUET2(lchip))
    {
        switch (num_flow)
        {
            case 256:
                driver_value = 0;
                break;
            case 128:
                driver_value = 1;
                break;
            case 64:
                driver_value = 2;
                break;
            case 32:
                driver_value = 3;
                break;
            default:
                return driver_value = 4;
        }
    }
    else
    {
        switch (num_flow)
        {
            case 16:
                driver_value = 0;
                break;
            case 32:
                driver_value = 1;
                break;
            case 64:
                driver_value = 2;
                break;
            case 128:
                driver_value = 3;
                break;
            case 256:
                driver_value = 4;
                break;
            case 512:
                driver_value = 5;
                break;
            case 1024:
                driver_value = 6;
                break;
            case 2048:
                driver_value = 7;
                break;
            case 4096:
                driver_value = 8;
                break;
            case 8192:
                driver_value = 9;
                break;
            default:
                driver_value = 7;
        }
    }

    return driver_value;
}
STATIC char *
_sys_usw_linkagg_mode2str(uint8 mode)
{
    char *str = NULL;

    switch (mode)
    {
        case CTC_LINKAGG_MODE_4:
        {
            str = "mode 4";
            break;
        }
        case CTC_LINKAGG_MODE_8:
        {
            str = "mode 8";
            break;
        }
        case CTC_LINKAGG_MODE_16:
        {
            str = "mode 16";
            break;
        }
        case CTC_LINKAGG_MODE_32:
        {
            str = "mode 32";
            break;
        }
        case CTC_LINKAGG_MODE_64:
        {
            str = "mode 64";
            break;
        }
        case CTC_LINKAGG_MODE_56:
        {
            str = "mode 56";
            break;
        }
        case CTC_LINKAGG_MODE_FLEX:
        {
            str = "mode flex";
            break;
        }
        default:
        {
            str = "unknown";
            break;
        }
    }

    return str;
}

STATIC uint32
_sys_usw_dlb_get_real_member_num(uint8 lchip, uint16 tid)
{
    uint32 cmd_r;
    uint32 field_val = 0;

    cmd_r = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggMemNum_f);
    DRV_FIELD_IOCTL(lchip, tid, cmd_r, &field_val);

    return field_val;
}

STATIC int32
_sys_usw_add_member_channel(uint8 lchip, uint16 tid, uint32 gport)
{
    uint32 cmd = 0;
    DsLinkAggregateChannel_m linkagg_channel;
    uint32 channel_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x gport =  %d \n", tid, gport);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
    channel_id = SYS_USW_CHANNEL_ENCODE(channel_id);

    SetDsLinkAggregateChannel(V, groupEn_f, &linkagg_channel, 1);
    SetDsLinkAggregateChannel(V, groupType_f, &linkagg_channel, 0);     /* port level */
    SetDsLinkAggregateChannel(V, linkChangeEn_f, &linkagg_channel, 0);
    SetDsLinkAggregateChannel(V, u1_g1_linkAggregationGroup_f, &linkagg_channel, tid);

    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_del_member_channel(uint8 lchip, uint16 tid, uint32 gport)
{
    uint32 cmd = 0;
    DsLinkAggregateChannel_m linkagg_channel;
    uint32 channel_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x gport =  %d \n", tid, gport);

    sal_memset(&linkagg_channel, 0, sizeof(linkagg_channel));
    dmps_port_info.gport = gport;

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
    channel_id = SYS_USW_CHANNEL_ENCODE(channel_id);

    cmd = DRV_IOW(DsLinkAggregateChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &linkagg_channel));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dlb_add_member(uint8 lchip, uint16 tid, uint16 port_index, uint16 lport)
{
    uint32 cmd = 0;
    uint32 channel_id = 0;
    uint8 gchip = 0;
    uint8 step = 0;
    DsLinkAggregateMemberSet_m mem_set;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    sal_memset(&mem_set, 0, sizeof(mem_set));

    if (port_index > MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Overrange the max number of dlb!\n");
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    dmps_port_info.gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, lport);

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));


    cmd = DRV_IOR(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd, &mem_set));

    step = DsLinkAggregateMemberSet_array_1_channelId_f - DsLinkAggregateMemberSet_array_0_channelId_f;

    SetDsLinkAggregateMemberSet(V, array_0_channelId_f + port_index * step, &mem_set, SYS_USW_CHANNEL_ENCODE(channel_id));
    SetDsLinkAggregateMemberSet(V, array_0_localPhyPort_f + port_index * step, &mem_set, lport);
    SetDsLinkAggregateMemberSet(V, array_0_sliceId_f + port_index * step, &mem_set, SYS_MAP_DRV_LPORT_TO_SLICE(lport));
    SetDsLinkAggregateMemberSet(V, array_0_valid_f + port_index * step, &mem_set, 1);

    cmd = DRV_IOW(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd, &mem_set));

    CTC_ERROR_RETURN(_sys_usw_add_member_channel(lchip, tid, dmps_port_info.gport));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dlb_del_member(uint8 lchip, uint16 tid, uint16 port_index, uint16 tail_index, uint32 gport)
{
    uint32 cmd = 0;
    uint16 channel_id = 0;
    uint32 local_phy_port = 0;
    uint32 slice_id = 0;
    uint32 valid = 0;
    uint8 step = 0;
    DsLinkAggregateMemberSet_m mem_set;

    sal_memset(&mem_set, 0, sizeof(mem_set));

    if ((port_index > MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM)) || (tail_index > MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM)))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Overrange the max number of dlb!\n");
        return CTC_E_INVALID_PARAM;
    }

    cmd = DRV_IOR(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd, &mem_set));
    step = DsLinkAggregateMemberSet_array_1_channelId_f - DsLinkAggregateMemberSet_array_0_channelId_f;

    if (port_index != tail_index)
    {
        /*copy the last one to the removed position*/
        channel_id = GetDsLinkAggregateMemberSet(V, array_0_channelId_f + tail_index * step, &mem_set);
        local_phy_port = GetDsLinkAggregateMemberSet(V, array_0_localPhyPort_f + tail_index * step, &mem_set);
        slice_id = GetDsLinkAggregateMemberSet(V, array_0_sliceId_f + tail_index * step, &mem_set);
        valid = GetDsLinkAggregateMemberSet(V, array_0_valid_f + tail_index * step, &mem_set);

        SetDsLinkAggregateMemberSet(V, array_0_channelId_f + port_index * step, &mem_set, channel_id);
        SetDsLinkAggregateMemberSet(V, array_0_localPhyPort_f + port_index * step, &mem_set, local_phy_port);
        SetDsLinkAggregateMemberSet(V, array_0_sliceId_f + port_index * step, &mem_set, slice_id);
        SetDsLinkAggregateMemberSet(V, array_0_valid_f + port_index * step, &mem_set, valid);
    }

    /* set the last one to reserve */
    SetDsLinkAggregateMemberSet(V, array_0_valid_f + tail_index * step, &mem_set, 0);


    cmd = DRV_IOW(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd, &mem_set));

    CTC_ERROR_RETURN(_sys_usw_del_member_channel(lchip, tid, gport));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_linkagg_reverve_member(uint8 lchip, uint16 tid, uint8 start)
{
    uint32 cmd_member_set = 0;
    uint16 index = 0;
    uint8 step = 0;
    DsLinkAggregateMemberSet_m mem_set;

    sal_memset(&mem_set, 0, sizeof(mem_set));

    cmd_member_set = DRV_IOR(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd_member_set, &mem_set));
    step = DsLinkAggregateMemberSet_array_1_channelId_f - DsLinkAggregateMemberSet_array_0_channelId_f;

    for (index = start; index < 16; index++)
    {
        SetDsLinkAggregateMemberSet(V, array_0_valid_f + index * step, &mem_set, 0);
    }

    cmd_member_set = DRV_IOW(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd_member_set, &mem_set));

    return CTC_E_NONE;
}

/**
 @brief The function is to clear flow active in linkagg group
*/
STATIC int32
_sys_usw_linkagg_clear_flow_active(uint8 lchip, uint8 tid, uint8 is_spm, uint32 agg_base, uint32 flow_num)
{
    uint32 cmd_r = 0;
    uint32 cmd_w = 0;
    DsLinkAggregateGroup_m ds_link_aggregate_group;
    ds_t ds_tbl;

    uint32 index = 0;
    uint32 tbl_id = 0;
    uint32 field_id = 0;

    sal_memset(&ds_link_aggregate_group, 0, sizeof(DsLinkAggregateGroup_m));
    sal_memset(&ds_tbl, 0, sizeof(ds_tbl));


    cmd_r = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd_r, &ds_link_aggregate_group));

    agg_base = is_spm ? agg_base : GetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_link_aggregate_group);
    flow_num = is_spm ? flow_num : _sys_usw_linkagg_driver2flows(lchip, GetDsLinkAggregateGroup(V, linkAggFlowNum_f, &ds_link_aggregate_group), is_spm);

    /* clear active */
    tbl_id = is_spm ? DsAntFlow_t : (DRV_FROM_TMM(lchip) ? DsLagDlbFlowSetTable_t : DsLinkAggregateMember_t);
    field_id = is_spm ? DsAntFlow_active_f: (DRV_FROM_TMM(lchip) ? DsLagDlbFlowSetTable_active_f: DsLinkAggregateMember_active_f);

    cmd_r = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    cmd_w = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);


    for (index = 0; index < flow_num; index++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, agg_base+index, cmd_r, &ds_tbl));
        DRV_SET_FIELD_V(lchip, tbl_id, field_id, &ds_tbl, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, agg_base+index, cmd_w, &ds_tbl));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_linkagg_add_padding_mem(uint8 lchip, sys_linkagg_t* p_group, sys_linkagg_mem_t * p_linkagg_mem, uint16 start_index)
{
    uint16 mem_num = 0;
    uint16 index = 0;
    uint32 cmd_member_w = 0;
    uint32 cmd_member_r = 0;
    uint16 agg_base = 0;
    DsLinkAggregateMember_m ds_linkagg_member;
    uint8 temp = 0;
    uint8 act_mem_num = 0;

    sal_memset(&ds_linkagg_member, 0, sizeof(ds_linkagg_member));

    cmd_member_w = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
    cmd_member_r = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
    agg_base = p_group->member_base;
    mem_num = p_group->max_member_num;

    sal_memset(&ds_linkagg_member, 0, sizeof(ds_linkagg_member));

    act_mem_num = p_linkagg_mem->mem_valid_num;

    for (index = start_index + 1; index < mem_num; index++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (agg_base + (temp % act_mem_num)), cmd_member_r, &ds_linkagg_member));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (agg_base + index), cmd_member_w, &ds_linkagg_member));
        temp++;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_get_repeat_member_cnt(uint8 lchip, sys_linkagg_t* p_group, uint16 gport, uint16* repeat_cnt)
{
    uint16 mem_idx = 0;
    uint16 loop_num = 0;
    sys_linkagg_port_t* port_node = NULL;

    (*repeat_cnt) = 0;
    if (1 >= p_group->real_member_num)
    {
        return CTC_E_NONE;
    }
    loop_num = p_group->port_cnt;
    for (mem_idx = 0; mem_idx < loop_num; mem_idx++)
    {
        port_node = p_group->port_list[mem_idx];
        if(port_node && (gport == port_node->gport))
        {
            (*repeat_cnt)++;
        }
    }
    (*repeat_cnt)--;
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gport:%d, repeat_cnt:%d\n", gport,*repeat_cnt);
    return CTC_E_NONE;
}

/**
 @brief The function is update asic table, add/remove member port from linkagg.
*/
STATIC int32
_sys_usw_linkagg_update_table(uint8 lchip, sys_linkagg_t* p_group, sys_linkagg_mem_t* p_linkagg_mem, bool is_add_port, uint8 replace)
{
    uint32 cmd_group_r = 0;
    uint32 cmd_group_w = 0;
    uint32 cmd_member_w = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
    uint32 cmd_member_r = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
    uint16 port_cnt = 0;
    uint16 mem_base = p_group->member_base;
    DsLinkAggregateMember_m ds_linkagg_member;
    DsLinkAggregateGroup_m ds_linkagg_group;
    uint16 lport = 0;
    int32 ret = 0;
    uint16 tail_index = 0;
    uint8 dest_chip_id = 0;
    uint8 is_local_chip = 0;
    uint16 port_index  = p_linkagg_mem->port_index;
    uint16 repeat_mem_cnt = 0;
    uint8 unbind_mc = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    sal_memset(&ds_linkagg_member, 0, sizeof(DsLinkAggregateMember_m));
    sal_memset(&ds_linkagg_group, 0, sizeof(DsLinkAggregateGroup_m));

    tail_index = p_linkagg_mem->mem_valid_num;

    dest_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(p_linkagg_mem->gport);
    is_local_chip = sys_usw_chip_is_local(lchip, dest_chip_id);

    if (TRUE == is_add_port)
    {
        port_cnt = p_linkagg_mem->port_cnt;

        /*update DsLinkAggregateMember_t */
        lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_linkagg_mem->gport);

        switch(p_linkagg_mem->linkagg_mode)
        {
            case CTC_LINKAGG_MODE_STATIC:
            case CTC_LINKAGG_MODE_STATIC_FAILOVER:
            case CTC_LINKAGG_MODE_RR:
            {
                uint32 channel_id = 0;
                dmps_port_info.gport = p_linkagg_mem->gport;
                CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
                SetDsLinkAggregateMember(V, destId_f, &ds_linkagg_member, lport);
                SetDsLinkAggregateMember(V, destChipId_f, &ds_linkagg_member, dest_chip_id);
                SetDsLinkAggregateMember(V, destChannelId_f, &ds_linkagg_member, is_local_chip ? SYS_USW_CHANNEL_ENCODE(channel_id) : 0);

                cmd_member_w = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, (mem_base + port_index), cmd_member_w, &ds_linkagg_member));

                if (p_linkagg_mem->linkagg_mode == CTC_LINKAGG_MODE_STATIC_FAILOVER)
                {
                    CTC_ERROR_RETURN(_sys_usw_hw_sync_add_member(lchip, p_linkagg_mem->tid, p_linkagg_mem->gport));
                }

                if (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_SPM_EN) && is_local_chip)
                {
                    CTC_ERROR_RETURN(_sys_usw_add_member_channel(lchip, p_linkagg_mem->tid, p_linkagg_mem->gport));
                }
                break;
            }
            case CTC_LINKAGG_MODE_DLB:
            {
                CTC_ERROR_RETURN(_sys_usw_dlb_add_member(lchip, p_linkagg_mem->tid, port_index, lport));
                break;
            }
            default:
                return CTC_E_NOT_SUPPORT;
        }

        if (0 == replace)
        {
            /* update DsLinkAggregateGroup_t linkagg port cnt */
            cmd_group_r = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_linkagg_mem->tid, cmd_group_r, &ds_linkagg_group));
            /*Only D2 & TM do local member first need to think about lmpf cancel */
            if (!DRV_FROM_TMM(lchip) && p_group->cfg_lmpf && (!(p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) && (p_group->tid) > MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)))
            {
                SetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_linkagg_group, 0);
            }
            else
            {
                SetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_linkagg_group, port_cnt);
            }
            cmd_group_w = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_linkagg_mem->tid, cmd_group_w, &ds_linkagg_group));
        }
        if (p_linkagg_mem->need_pad)
        {
            ret = _sys_usw_linkagg_add_padding_mem(lchip, p_group, p_linkagg_mem, p_linkagg_mem->mem_valid_num);
            if (ret < 0)
            {
                return ret;
            }
        }
    }
    else
    {
        /*before this function calling, the port cnt has been decreased.*/
        port_cnt = p_linkagg_mem->port_cnt;
        lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_linkagg_mem->gport);

        /* update DsLinkAggregateGroup_t linkagg port cnt */
        if (0 == replace)
        {
            cmd_group_r = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_linkagg_mem->tid, cmd_group_r, &ds_linkagg_group));
            /*Only D2 & TM do local member first need to think about lmpf cancel */
            if (!DRV_FROM_TMM(lchip) && p_group->cfg_lmpf && (!(p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) && (p_group->tid) > MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)))
            {
                SetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_linkagg_group, 0);
            }
            else
            {
                SetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_linkagg_group, port_cnt);
            }

            cmd_group_w = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_linkagg_mem->tid, cmd_group_w, &ds_linkagg_group));
        }
        // whether the deleted member is last one
        CTC_ERROR_RETURN(_sys_usw_linkagg_get_repeat_member_cnt(lchip, p_group, p_linkagg_mem->gport, &repeat_mem_cnt));

        switch(p_linkagg_mem->linkagg_mode)
        {
            case CTC_LINKAGG_MODE_STATIC:
            case CTC_LINKAGG_MODE_STATIC_FAILOVER:
            case CTC_LINKAGG_MODE_RR:
            {
                if (0 == port_cnt)
                {
                    cmd_member_w = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (mem_base + port_index), cmd_member_w, &ds_linkagg_member));
                }
                else
                {
                    if(CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER))
                    {
                        uint16 tmp_index = port_index;
                        for(;tmp_index < tail_index; tmp_index++)
                        {
                            CTC_ERROR_RETURN(DRV_IOCTL(lchip, tmp_index+mem_base+1, cmd_member_r, &ds_linkagg_member));
                            CTC_ERROR_RETURN(DRV_IOCTL(lchip, tmp_index+mem_base, cmd_member_w, &ds_linkagg_member));
                        }
                    }
                    else
                    {
                        if (port_index != tail_index)
                        {
                            /*copy the last one to the removed port position,and remove member port from linkagg at tail*/
                            CTC_ERROR_RETURN(DRV_IOCTL(lchip, (mem_base + tail_index), cmd_member_r, &ds_linkagg_member));
                            CTC_ERROR_RETURN(DRV_IOCTL(lchip, (mem_base + port_index), cmd_member_w, &ds_linkagg_member));
                        }
                    }
                    if (p_linkagg_mem->need_pad)
                    {
                        CTC_ERROR_RETURN(_sys_usw_linkagg_add_padding_mem(lchip, p_group, p_linkagg_mem, tail_index - 1));
                    }
                }

                if (p_linkagg_mem->linkagg_mode == CTC_LINKAGG_MODE_STATIC_FAILOVER)
                {
                    CTC_ERROR_RETURN(_sys_usw_hw_sync_del_member(lchip, p_linkagg_mem->tid, p_linkagg_mem->gport));
                }

                dest_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(p_linkagg_mem->gport);
                if (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_SPM_EN) && is_local_chip && 0 == repeat_mem_cnt)
                {
                    CTC_ERROR_RETURN(_sys_usw_del_member_channel(lchip, p_linkagg_mem->tid, p_linkagg_mem->gport));
                }
                break;
            }
            case CTC_LINKAGG_MODE_DLB:
            {
                CTC_ERROR_RETURN(_sys_usw_dlb_del_member(lchip, p_linkagg_mem->tid, port_index, tail_index, p_linkagg_mem->gport));
                break;
            }
            default:
                return CTC_E_NOT_SUPPORT;
        }
    }

    unbind_mc = p_group->is_lag ? 1 : 0;
    /*update mcast linkagg bitmap*/
    if (is_local_chip && ((p_linkagg_mem->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)  
            && !CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
            || ((CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
            && DRV_IS_TSINGMA(lchip) && (p_group->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)))))
    {
        if (((is_add_port == TRUE) || ((is_add_port == FALSE) && (repeat_mem_cnt == 0))) && !unbind_mc)
        {
            CTC_ERROR_RETURN(sys_usw_port_api_update_mc_linkagg(lchip, p_linkagg_mem->tid, lport, is_add_port));
        }
    }

    return CTC_E_NONE;
}

/**
 @brief The function is to check whether the port is member of the linkagg.
*/
STATIC bool
_sys_usw_linkagg_port_is_member(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint16* index, uint16* hw_index)
{
    uint16 loop = 0;
    sys_linkagg_port_t* port_node = NULL;
    uint8 find_flag = 0;

    *index = CTC_MAX_UINT16_VALUE; /*indicate  uc lag member is not found  */
    for (loop = 0; loop < p_group->port_cnt; loop++)
    {
        port_node = p_group->port_list[loop];
        if (port_node && (port_node->gport == gport ))
        {
            *index = loop;
            find_flag = 1;
            break;
         }
    }

    if (hw_index && find_flag)
    {
        uint16 mem_num = 0;
        uint16 mem_base = 0;
        uint32 cmd_member = 0;
        uint8  chip_id = 0;
        uint16 destId = 0;
        uint32 gport_temp = 0;
        DsLinkAggregateMember_m ds_linkagg_member;
        mem_base = p_group->member_base;
        mem_num = p_group->real_member_num;
        sal_memset(&ds_linkagg_member, 0, sizeof(ds_linkagg_member));
        cmd_member = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
        if (!(p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST))
        {
            *hw_index = *index;
        }
        else
        {
            for (loop = mem_base; loop < (mem_base + mem_num); loop++)
            {
               CTC_ERROR_RETURN(DRV_IOCTL(lchip, loop, cmd_member, &ds_linkagg_member));
               chip_id = GetDsLinkAggregateMember(V, destChipId_f, &ds_linkagg_member);
               destId = GetDsLinkAggregateMember(V, destId_f, &ds_linkagg_member);
               gport_temp = CTC_MAP_LPORT_TO_GPORT(chip_id, destId);
               if (gport_temp == gport)
               {
                   *hw_index = loop - mem_base;
                   break;
               }
            }
        }
    }

    return find_flag ? TRUE:FALSE;
}

STATIC int32
_sys_usw_linkagg_dlb_set_load_quality_threshold(uint8 lchip, uint32 thrd)
{
    uint32 cmd = 0;
    uint32 th_step = 0;
    uint32 factors[] = { 1, 5, 10, 20, 25, 40, 50, 100};
    uint8 i = 0;
    DlbChanMaxLoadByteCnt_m dlb_load;

    sal_memset(&dlb_load, 0, sizeof(dlb_load));
    if (thrd * factors[7] > 0x7fffff) 
    {
        /* Hardware limits load size threshold to 23 bits */
        return CTC_E_INVALID_PARAM;
    }
    th_step = DlbChanMaxLoadByteCnt_maxLoadThreshold1_f - DlbChanMaxLoadByteCnt_maxLoadThreshold0_f;
    for(i = 0; i < 8; i++)
    {
        SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold0_f + th_step * i, &dlb_load,  thrd * factors[i]);
    }
    cmd = DRV_IOW(DlbChanMaxLoadByteCnt_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &dlb_load));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_lag_engine_dlb_init(uint8 lchip)
{
    uint32 value = 0;
    uint32 cmd = 0;
    /*uint32 core_frequecy = 0;*/
    uint8  i = 0;
    LagEngineDreTimerCtl_m lag_engine_dre_ctl;
    LagEngineCtl_m lag_engine_ctl;
    LagEngineDlbCtl_m lag_engine_dlb_ctl;
    DlbChanMaxLoadByteCnt_m chan_max_load_byte;
    uint16 chan_id = 0;

    if (MCHIP_LAG(lchip)->dlb_init)
    {
        return MCHIP_LAG(lchip)->dlb_init(lchip);
    }

    /*useless for TMM begin*/
    sal_memset(&lag_engine_dre_ctl, 0, sizeof(lag_engine_dre_ctl));
    sal_memset(&lag_engine_ctl, 0, sizeof(lag_engine_ctl));
    sal_memset(&lag_engine_dlb_ctl, 0, sizeof(lag_engine_dlb_ctl));
    sal_memset(&chan_max_load_byte, 0, sizeof(chan_max_load_byte));

    /*core_frequecy = sys_usw_get_core_freq(lchip, 0);*/

    /* 1. config LagEngineDreTimerCtl_m and RefDivQMgrEnqDrePulse_t for Tp and Rp, if Tp=1us, Rp=1/2,
       than the history load will be subtract to 0 every 2ms */
    SetLagEngineDreTimerCtl(V, chanDreUpdEn_f, &lag_engine_dre_ctl, 1);
    SetLagEngineDreTimerCtl(V, chanDreInterval_f, &lag_engine_dre_ctl, 1);
     /*-V5.0 SetLagEngineDreTimerCtl(V, chanDreMaxPtr_f, &lag_engine_dre_ctl, 63);*/
    /* Rp = 1/(2^chanDreDiscountShift) = 1/2 */
    for (i = 0; i < 64; ++i)
    {
        SetLagEngineDreTimerCtl(V, array_0_chanDreDiscountShift_f + i, &lag_engine_dre_ctl, 1);
    }

    cmd = DRV_IOW(LagEngineDreTimerCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_dre_ctl));

    /* Config load pulse timer for Tp=1us, [30:8] pulse : [7:0] pulse_frac , 0x9c64*/
    value = (1 * 156250 / 1000) << 8 | (1 * 156250 % 1000 * 256 / 1000); /* value=40000   */
    cmd = DRV_IOW(RefDivLinkAggDrePulse_t, RefDivLinkAggDrePulse_cfgRefDivLinkAggDrePulse_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    value = 0;
    cmd = DRV_IOW(RefDivLinkAggDrePulse_t, RefDivLinkAggDrePulse_cfgResetDivLinkAggDrePulse_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    /* 2. config DlbChanMaxLoadByteCnt_t and shift, unit is 100 usec */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold0_f, &chan_max_load_byte,  125);     /* 1G or 2.5G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold1_f, &chan_max_load_byte,  625);     /* 5G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold2_f, &chan_max_load_byte,  1250);    /* 10G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold3_f, &chan_max_load_byte,  2500);    /* 20G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold4_f, &chan_max_load_byte,  3125);    /* 25G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold5_f, &chan_max_load_byte,  5000);    /* 40G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold6_f, &chan_max_load_byte,  6250);    /* 50G */
    SetDlbChanMaxLoadByteCnt(V, maxLoadThreshold7_f, &chan_max_load_byte, 12500);    /* 100G */
    cmd = DRV_IOW(DlbChanMaxLoadByteCnt_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &chan_max_load_byte));

    if (!DRV_FROM_TMM(lchip))
    {
    value = 0;
    cmd = DRV_IOW(DlbEngineCtl_t, DlbEngineCtl_chanByteCountShift_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }

    /* config DlbChanMaxLoadType */
    for (chan_id = 0; chan_id < 64; chan_id++)
    {
        CTC_ERROR_RETURN(sys_usw_dmps_set_dlb_chan_type(lchip, chan_id));
    }

    /* 3. config LagEngineCtl_t for member move check */
    cmd = DRV_IOR(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl));

    SetLagEngineCtl(V, portLagMemberMoveCheckEn_f, &lag_engine_ctl, 1);
    SetLagEngineCtl(V, rrProtectDisable_f,&lag_engine_ctl, 0);
    SetLagEngineCtl(V, iLoopOamDestId_f, &lag_engine_ctl, SYS_RSV_PORT_ILOOP_ID);
    /*SetLagEngineCtl(V, chanBandwidthShift0_f, &lag_engine_ctl, 8);*/

    cmd = DRV_IOW(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl));

    /* 4. config LagEngineDlbCtl_t for dre counter */
    cmd = DRV_IOR(LagEngineDlbCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_dlb_ctl));

    SetLagEngineDlbCtl(V, dlbEn_f, &lag_engine_dlb_ctl, 1);
    SetLagEngineDlbCtl(V, byteCountShift_f, &lag_engine_dlb_ctl, 0);  /* unit of dre counter */
    SetLagEngineDlbCtl(V, ipg_f, &lag_engine_dlb_ctl, 20);     /* for dre ipg */

    cmd = DRV_IOW(LagEngineDlbCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_dlb_ctl));

    value = 1;
    cmd = DRV_IOW(LagEngineLinkState_t, LagEngineLinkState_linkState_f);
    for(chan_id=0; chan_id < MCHIP_CAP(SYS_CAP_NETWORK_CHANNEL_NUM); chan_id++)
    {
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &value));
    }
    /*useless for TMM end*/
    return CTC_E_NONE;
}

STATIC int32 _sys_usw_linkagg_add_db(uint8 lchip, uint16 tid, ctc_linkagg_group_t* p_linkagg_grp, sys_linkagg_t** p_group_out)
{
    uint32 mem_num = 0;
    uint32 mem_base = 0;
    uint32 port_list_num = 0;
    int32  ret = CTC_E_NONE;
    sys_linkagg_t* p_group = NULL;
    sys_usw_opf_t opf = {0};
    sys_linkagg_port_t **p_port_list = NULL;
    uint8 is_nonuc_group = 0;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    mem_num = p_linkagg_grp->member_num;
    if (DRV_FROM_TMM(lchip) && (tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)) && (CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)))
    {
        mem_num = 0;
        is_nonuc_group = 1;
    }
    else if(CTC_LINKAGG_MODE_DLB == p_linkagg_grp->linkagg_mode && DRV_FROM_TMM(lchip))
    {
        if (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX)
        {
            mem_num = p_linkagg_grp->member_num;
        }
        else
        {
            SYS_LINKAGG_GET_GROUP_DLB_FLOW_NUM(tid, mem_num);
        }
        CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset(lchip, DsLagDlbFlowSetTable_t, 0, mem_num, 1, &mem_base), ret, error_proc);
    }
    else if(p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX  && p_linkagg_grp->member_num)
    {
        mem_num = p_linkagg_grp->member_num;
        /*DsLinkAggregateGroup_linkAggMemNum_f only have 8bits*/
        if (p_linkagg_grp->linkagg_mode != CTC_LINKAGG_MODE_DLB)
        {
            mem_num =  (mem_num == 256) ? 255 : mem_num;
        }
        sal_memset(&opf, 0, sizeof(opf));
        opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;
        opf.pool_index = 0;
        opf.multiple = MCHIP_CAP(SYS_CAP_LINKAGG_FRAGMENT_SIZE);
        if(mem_num > (MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM)-sys_usw_opf_get_alloced_cnt(SYS_PP_BASE(lchip), &opf)))
        {
            ret = CTC_E_NO_RESOURCE;
            goto error_proc;
        }
        ret = sys_usw_opf_alloc_offset(SYS_PP_BASE(lchip), &opf, mem_num, &mem_base);
        if (ret == CTC_E_NO_RESOURCE)
        {
            _sys_usw_linkagg_fragment(lchip);
            CTC_ERROR_GOTO(sys_usw_opf_alloc_offset(SYS_PP_BASE(lchip), &opf, mem_num, &mem_base), ret, error_proc);
        }
        else if (ret)
        {
            goto error_proc;
        }
    }
    else  if(p_usw_linkagg_master[lchip]->linkagg_mode != CTC_LINKAGG_MODE_FLEX)
    {
        SYS_LINKAGG_GET_GROUP_MEMBER_NUM(tid, mem_num);
        SYS_LINKAGG_GET_GROUP_MEMBER_BASE(tid, mem_num, mem_base)
        /*DsLinkAggregateGroup_linkAggMemNum_f only have 8bits*/
        if (p_linkagg_grp->linkagg_mode != CTC_LINKAGG_MODE_DLB)
        {
            mem_num =  (mem_num == 256) ? 255 : mem_num;
        }
    }

    p_group = mem_malloc(MEM_LINKAGG_MODULE, sizeof(sys_linkagg_t));
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_1;
    }

    port_list_num = CTC_LINKAGG_MODE_DLB == p_linkagg_grp->linkagg_mode ? MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM) : mem_num;
    if(port_list_num)
    {
        p_port_list = mem_malloc(MEM_LINKAGG_MODULE, port_list_num * sizeof(void*));
        if(!p_port_list)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto error_2;
        }
        sal_memset(p_port_list, 0, port_list_num * sizeof(void*));
    }
    sal_memset(p_group, 0, sizeof(sys_linkagg_t));
    p_group->max_member_num = mem_num;
    p_group->member_base = is_nonuc_group?CTC_MAX_UINT16_VALUE:mem_base; /*indicate  nonuc group */
    p_group->mode = p_linkagg_grp->linkagg_mode;
    p_group->port_list = p_port_list;
    p_group->tid = tid;
    p_group->flag = p_linkagg_grp->flag;
    p_group->lsh_mode = p_linkagg_grp->lsh_mode;
    if (!ctc_vector_add(p_usw_linkagg_master[lchip]->group_vector, tid, p_group))
    {
        ret = CTC_E_NO_MEMORY;
        goto error_3;
    }

    if(p_group_out)
    {
        *p_group_out = p_group;
    }

    return CTC_E_NONE;
error_3:
    if(p_port_list)
    {
        mem_free(p_port_list);
    }
error_2:
    if(p_group)
    {
        mem_free(p_group);
    }
error_1:
    if (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX)
    {
        sys_usw_opf_free_offset(SYS_PP_BASE(lchip), &opf, mem_num, mem_base);
    }
error_proc:
    if (CTC_LINKAGG_MODE_DLB == p_linkagg_grp->linkagg_mode && DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_RETURN(sys_usw_ftm_free_table_offset(lchip, DsLagDlbFlowSetTable_t, 0, mem_num, mem_base));
    }
    return ret;
}

int32
_sys_usw_linkagg_remove_db(uint8 lchip, uint16 tid)
{
    sys_usw_opf_t opf;
    sys_linkagg_t* p_group = NULL;
    uint16 loop = 0;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        return CTC_E_NONE;
    }
    if(p_group->max_member_num)
    {
         if (CTC_LINKAGG_MODE_DLB == p_group->mode && DRV_FROM_TMM(lchip))
         {
             sys_usw_ftm_free_table_offset(lchip, DsLagDlbFlowSetTable_t,
                                                            0, p_group->max_member_num, p_group->member_base);
         }
         else
         {
             sal_memset(&opf, 0, sizeof(opf));
             opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;
             sys_usw_opf_free_offset(lchip, &opf, p_group->max_member_num, p_group->member_base);
         }
    }
    ctc_vector_del(p_usw_linkagg_master[lchip]->group_vector, tid);
    for (loop = 0; loop < p_group->port_cnt; loop++ )
    {
        mem_free(p_group->port_list[loop]);
    }
    mem_free(p_group->port_list);
    mem_free(p_group);

    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_add_port_to_db(uint8 lchip, void* p_lag_group, uint32 gport, uint8 nonuc_block_en, uint8 is_local_chip)
{
    uint16 loop = 0;
    sys_linkagg_port_t* port_node;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;

    port_node = mem_malloc(MEM_LINKAGG_MODULE,  sizeof(sys_linkagg_port_t));
    if(!port_node)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return  CTC_E_NO_MEMORY;
    }
    sal_memset(port_node, 0, sizeof(sys_linkagg_port_t));

    loop = p_group->port_cnt;
    if(CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER))
    {
        for (; loop > 0; loop--)
        {
            if(SYS_LINKAGG_MAP_GPORT_TO_GCHIP_LPORT(gport) >= SYS_LINKAGG_MAP_GPORT_TO_GCHIP_LPORT(p_group->port_list[loop - 1]->gport))
            {
                break;
            }
            p_group->port_list[loop] = p_group->port_list[loop - 1];
        }
    }
    port_node->is_local = is_local_chip;
    port_node->nonuc_block_en = nonuc_block_en;
    port_node->gport = gport;
    p_group->port_list[loop] = port_node;
    p_group->port_cnt++;

    if ( is_local_chip)
    {
        p_group->local_port_cnt++;
    }
    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_remove_port_to_db(uint8 lchip, void* p_lag_group, uint32 gport)
{
    sys_linkagg_port_t* port_node = NULL;
    uint16 loop = 0;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;
    uint8 is_local_chip = 0;

    for (loop = 0; loop < p_group->port_cnt; loop++ )
    {
        if (p_group->port_list[loop]->gport == gport)
        {
            port_node = p_group->port_list[loop];
            is_local_chip = port_node->is_local;
            break;
        }
    }


    if (loop < p_group->port_cnt)
    {
        if(CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER))
        {
            for (; loop < p_group->port_cnt - 1; loop++)
            {
                p_group->port_list[loop] = p_group->port_list[loop + 1];
            }
        }
        else
        {
            p_group->port_list[loop] = p_group->port_list[p_group->port_cnt - 1];
        }
        mem_free(port_node);
        p_group->port_cnt--;
        if (is_local_chip)
        {
            p_group->local_port_cnt--;
        }
    }

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_linkagg_free_node_data(void* node_data, void* user_data)
{
    uint8 lchip = *(uint8*)user_data;
    uint16 loop = 0;
    sys_linkagg_t* p_group = (sys_linkagg_t*)node_data;

    if (DRV_FROM_TMM(lchip))
    {
        if (CTC_LINKAGG_MODE_DLB == p_group->mode )
        {
            sys_usw_ftm_free_table_offset(lchip, DsLagDlbFlowSetTable_t,
                                                           0, p_group->max_member_num, p_group->member_base);
        }

        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN)
        {
            uint32 cmd = 0;
            uint32 antflow_base = 0;
            uint32 flow_num = 0;
            cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_antFlowTableBase_f);
            DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &antflow_base);
            cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggFlowNum_f);
            DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &flow_num);
            sys_usw_ftm_free_table_offset(lchip, DsAntFlow_t, 0, _sys_usw_linkagg_driver2flows(lchip, flow_num, 1),
                                            antflow_base << SYS_LINKAGG_SPM_TBL_BASE_WIDTH);
        }
    }

    for (loop = 0; loop < p_group->port_cnt; loop++ )
    {
        mem_free(p_group->port_list[loop]);
    }
    mem_free(p_group->port_list);
    mem_free(p_group);

    return CTC_E_NONE;
}
STATIC uint8
_sys_usw_linkagg_find_rr_profile_id(uint8 lchip, uint16 tid)
{
    uint8 loop;
    if(DRV_IS_DUET2(lchip))
    {
        return tid;
    }
    for(loop=0; loop < 16; loop++)
    {
        if(!CTC_IS_BIT_SET(p_usw_linkagg_master[lchip]->rr_profile_bmp, loop))
        {
            break;
        }
    }
    return loop;
}

int32 _sys_usw_linkagg_group_param_check(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp )
{
    uint32 min_th = 0;
    uint32 max_th = 0;

    CTC_PTR_VALID_CHECK(p_linkagg_grp);
    SYS_TID_VALID_CHECK(p_linkagg_grp->tid);
    CTC_MAX_VALUE_CHECK(p_linkagg_grp->lsh_mode,CTC_LINKAGG_LSH_MODE_MAX - 1);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "linkAggId = 0x%x\n", p_linkagg_grp->tid);

    if(CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER) && p_linkagg_grp->linkagg_mode != CTC_LINKAGG_MODE_STATIC)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Only static mode support member in ascend order\n");
        return CTC_E_INVALID_PARAM;
    }
    if(CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_SPM_EN))
    {
        /*TsingMa.MX:spm flow num range: 8K/16K/32K/64K/128k/256K*/
        if (!((p_linkagg_grp->flow_num & (p_linkagg_grp->flow_num- 1)) == 0
            && p_linkagg_grp->flow_num >= 8*1024 && p_linkagg_grp->flow_num <= 256*1024))
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    /*after TsingMa support nonuc detach and not support nonuc detach and member first*/
    if((CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && !DRV_FROM_TM(lchip))
     || (CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)))
    {
        return CTC_E_INVALID_PARAM;
    }

    switch (p_linkagg_grp->linkagg_mode)
    {
        case CTC_LINKAGG_MODE_STATIC:
        {
            if(CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_RANDOM_RR))
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "static mode no support random rr!\n");
                return CTC_E_INVALID_PARAM;
            }
            /* in tsgingMa, mode 4 do not support static group for waste of member */
            if ((DRV_FROM_TM(lchip)) && CTC_LINKAGG_MODE_4 == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode 4 do not support static group!\n");
                return CTC_E_INVALID_PARAM;
            }

            if (CTC_LINKAGG_MODE_FLEX == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                if (p_linkagg_grp->member_num > SYS_LINKAGG_MEM_NUM_1 && DRV_IS_DUET2(lchip)) /*duet2 static mode member_num*/
                {
                    if (SYS_LINKAGG_MEM_NUM_2 != p_linkagg_grp->member_num &&
                        SYS_LINKAGG_MEM_NUM_3 != p_linkagg_grp->member_num &&
                        SYS_LINKAGG_MEM_NUM_4 != p_linkagg_grp->member_num)
                    {
                        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "static member_num invalid!\n");
                        return CTC_E_INVALID_PARAM;
                    }
                }
                else if(p_linkagg_grp->member_num > MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM))
                {
                    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "static member_num out of max_num!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }

            if (CTC_LINKAGG_MODE_FLEX != p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                /* nor flex mode do not support local member first */
                if (p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
                {
                    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "only flex mode  support local member first!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }

            break;
        }
        case CTC_LINKAGG_MODE_STATIC_FAILOVER:
        {
            if(CTC_FLAG_ISSET(p_linkagg_grp->flag,CTC_LINKAGG_GROUP_FLAG_RANDOM_RR) || \
                CTC_FLAG_ISSET(p_linkagg_grp->flag,CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER))
            {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode static failover do not support FLAG_RANDOM_RR or FLAG_MEM_ASCEND_ORDER!\n");
                return CTC_E_INVALID_PARAM;
            }
            /* mode 4 do not support failover group for waste of member */
            if (CTC_LINKAGG_MODE_4 == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode 4 do not support failover group !\n");
                return CTC_E_INVALID_PARAM;
            }

            if (SYS_LINKAGG_MEM_NUM_1 < p_linkagg_grp->member_num)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode static failover member_num invalid\n");
                return CTC_E_INVALID_PARAM;
            }

            if (CTC_LINKAGG_MODE_FLEX == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                /* static failover member_num range: 1~24 */
                if ( (0 == p_linkagg_grp->member_num) || (DRV_IS_DUET2(lchip) && p_linkagg_grp->member_num > SYS_LINKAGG_MEM_NUM_1))
                {
                    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "static failover member_num invalid!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }

            if (CTC_LINKAGG_MODE_FLEX != p_usw_linkagg_master[lchip]->linkagg_mode && p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "nor flex mode do not support local member first!\n");
                return CTC_E_INVALID_PARAM;
            }


            break;
        }
        case CTC_LINKAGG_MODE_RR:
        {
            if(CTC_FLAG_ISSET(p_linkagg_grp->flag,CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) || \
                CTC_FLAG_ISSET(p_linkagg_grp->flag,CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER))
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode rr do not support FLAG_LOCAL_MEMBER_FIRST or FLAG_MEM_ASCEND_ORDER!\n");
                return CTC_E_INVALID_PARAM;
            }
            /* mode 4 do not support rr group for waste of member */
            if (CTC_LINKAGG_MODE_4 == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode 4 do not support rr group!\n");
                return CTC_E_INVALID_PARAM;
            }

            if (p_linkagg_grp->tid > MCHIP_CAP(SYS_CAP_LINKAGG_RR_TID_MAX))
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");
                return CTC_E_BADID;
            }

            if (CTC_LINKAGG_MODE_FLEX == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                /* duet2 rr member_num range: 1~24, TsingMa:rr member_num range: 1-255*/
                uint16 rr_max_member = DRV_IS_DUET2(lchip)? SYS_LINKAGG_MEM_NUM_1 : MCHIP_CAP(SYS_CAP_LINKAGG_RR_MAX_MEM_NUM);
                if ((0 == p_linkagg_grp->member_num) || (p_linkagg_grp->member_num > rr_max_member))
                {
                    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "rr member_num invalid!\n");
                    return CTC_E_INVALID_PARAM;
                }
            }

            break;
        }
        case CTC_LINKAGG_MODE_DLB:
        {
            if(p_linkagg_grp->lsh_mode)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "dlb mode no support link selfhealing!\n");
                return CTC_E_INVALID_PARAM;
            }

            if(CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_SPM_EN))
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "dlb mode no support session preservation!\n");
                return CTC_E_NOT_SUPPORT;
            }

            /* mode 64 do not support dlb group for lack of member */
            if (CTC_LINKAGG_MODE_64 == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mode 64 do not support dlb group for lack of member!\n");
                return CTC_E_INVALID_PARAM;
            }

            /* in mode 56, only the first 8 group can be dlb group */
            if (CTC_LINKAGG_MODE_56 == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                if (p_linkagg_grp->tid > MCHIP_CAP(SYS_CAP_LINKAGG_MODE56_DLB_TID_MAX))
                {
                    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");
                    return CTC_E_BADID;
                }
            }

            if (CTC_LINKAGG_MODE_FLEX == p_usw_linkagg_master[lchip]->linkagg_mode)
            {
                /* duet2 dlb member_num range: 32/64/128/256
                 * TsingMa:dlb member_num range: 16/32/64/128/256/512/1024/2048
                 * TsingMa.MX:dlb member_num range: 16/32/64/128/256/512/1024/2048/4096/8192
                 */
                 if (DRV_IS_DUET2(lchip))
                 {
                     min_th = 32;
                     max_th = 256;
                 }
                 else if (DRV_IS_TSINGMA(lchip))
                 {
                     min_th = 16;
                     max_th = 2048;
                 }
                 else
                 {
                     min_th = 16;
                     max_th = 8192;
                 }

                 if (!((p_linkagg_grp->member_num & (p_linkagg_grp->member_num - 1)) == 0 &&
                     p_linkagg_grp->member_num >= min_th && p_linkagg_grp->member_num <= max_th))
                 {
                     SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "dlb member_num invalid!\n");
                     return CTC_E_INVALID_PARAM;
                 }
            }
            break;
        }
        default:
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "linkagg group mode error!\n");
            return CTC_E_NOT_SUPPORT;
    }
    return CTC_E_NONE;
}

int32
sys_usw_linkagg_bind_mirror(uint8 lchip, uint8 tid, uint8 is_add)
{
    int32 ret = CTC_E_NONE;
    SYS_LINKAGG_INIT_CHECK();
    LINKAGG_LOCK;
    if (MCHIP_LAG(lchip)->bind_mirror)
    {
        CTC_ERROR_GOTO(MCHIP_LAG(lchip)->bind_mirror(lchip, tid, is_add), ret, exit);
    }
    exit:
    LINKAGG_UNLOCK;
    return ret;
}

int32
_sys_usw_linkagg_get_pp_bmp(uint8 lchip, uint16 tid, uint16* pp_bmp)
{
    uint32 pp_id = 0;
    uint8 i = 0;
    int32 ret = CTC_E_NONE;
    sys_linkagg_t* p_group;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    *pp_bmp = 0;
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (!p_group)
    {
        return CTC_E_NOT_EXIST;
    }

    for (i = 0; i < p_group->port_cnt; i++)
    {
        if (!sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(p_group->port_list[i]->gport)))
        {
            continue;
        }
        dmps_port_info.gport = p_group->port_list[i]->gport;
        ret = sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PP_ID, &pp_id);
        CTC_BIT_SET(*pp_bmp, pp_id);
    }

    return ret;
}

int32
sys_usw_linkagg_get_pp_bmp(uint8 lchip, uint16 tid, uint16* pp_bmp)
{
    int32 ret = CTC_E_NONE;
    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(pp_bmp);

    LINKAGG_LOCK;
    ret = _sys_usw_linkagg_get_pp_bmp(lchip, tid, pp_bmp);
    LINKAGG_UNLOCK;

    return ret;
}

#define __APIs__

/**
 @brief The function is to init the linkagg module
*/
int32
sys_usw_linkagg_init(uint8 lchip, void* linkagg_global_cfg)
{
    int32 ret = CTC_E_NONE;
    uint8  gchip = 0;
    uint16 index = 0;
    uint32 core_frequecy = 0;
    uint32 cmd_timer = 0;
    ctc_linkagg_global_cfg_t* p_linkagg_global_cfg = NULL;
    DsLinkAggregateMember_m ds_linkagg_member;
    ds_t lag_engine_timer_ctl0;
    LagEngineCtl_m lag_engine_ctl;
//    MetFifoCtl_m metfifo_ctl;
    uint32 cmd = 0;
    uint32 field_val = 0;
    sys_usw_opf_t opf;
    uint32 cmd_chan_port = 0;
    uint8 is_from_tmm = DRV_FROM_TMM(lchip);
    uint16 linkagg_num;
    uint16 flow_num = 0;
    uint32* p_dma_mem = NULL;
#ifndef EMULATION_ENV
    uint16 mem_idx = 0;
    uint32 cmd_linkagg = 0;
    uint32 cmdr_chan_port = 0;
    DsPortChannelLag_m ds_linkagg_port;
    uint32  block_mask[16] = {0};
#endif

    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(linkagg_global_cfg);
    p_linkagg_global_cfg = (ctc_linkagg_global_cfg_t*)linkagg_global_cfg;
    CTC_MAX_VALUE_CHECK(p_linkagg_global_cfg->linkagg_mode, CTC_LINKAGG_MODE_FLEX);
    CTC_MAX_VALUE_CHECK(p_linkagg_global_cfg->bind_gport_disable, 1);

    if (NULL != p_usw_linkagg_master[lchip])
    {
        return CTC_E_NONE;
    }

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_linkagg_master, CTC_FEATURE_LINKAGG);
    /*init soft table*/
    p_usw_linkagg_master[lchip] = (sys_linkagg_master_t*)mem_malloc(MEM_LINKAGG_MODULE, sizeof(sys_linkagg_master_t));
    if (NULL == p_usw_linkagg_master[lchip])
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_proc;
    }

    sal_memset(p_usw_linkagg_master[lchip], 0, sizeof(sys_linkagg_master_t));

    ret = sal_mutex_create(&p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    if (ret || !p_usw_linkagg_master[lchip]->p_linkagg_mutex)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Create mutex fail\n");
        ret = CTC_E_NO_MEMORY;
        goto error_proc;
    }

    switch (p_linkagg_global_cfg->linkagg_mode)
    {
        case CTC_LINKAGG_MODE_4:
            linkagg_num = 4;
            break;

        case CTC_LINKAGG_MODE_8:
            linkagg_num = 8;
            break;

        case CTC_LINKAGG_MODE_16:
            linkagg_num = 16;
            break;

        case CTC_LINKAGG_MODE_32:
            linkagg_num = 32;
            break;

        case CTC_LINKAGG_MODE_64:
            linkagg_num = 64;
            break;

        case CTC_LINKAGG_MODE_56:
            linkagg_num = 56;
            break;
        case CTC_LINKAGG_MODE_FLEX:
            linkagg_num = MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM);
            break;
        default:
            ret = CTC_E_INVALID_PARAM;
            goto error_proc;
    }

    p_usw_linkagg_master[lchip]->linkagg_mode = p_linkagg_global_cfg->linkagg_mode;
    p_usw_linkagg_master[lchip]->bind_gport_disable = p_linkagg_global_cfg->bind_gport_disable;

    index = 2*MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM);
    p_usw_linkagg_master[lchip]->group_vector =  ctc_vector_init(4,CTC_VEC_BLOCK_NUM(index, 4));
    if (NULL == p_usw_linkagg_master[lchip]->group_vector)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Allocate vector for group fail!\n");
        ret = CTC_E_NO_MEMORY;
        goto error_proc;
    }

    ret = sys_usw_opf_init(lchip, &(p_usw_linkagg_master[lchip]->opf_type), 1, "Linkagg member opf");
    if (ret < 0)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "opf init fail!\n");
        goto error_proc;
    }

    sal_memset(&opf, 0, sizeof(opf));
    opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;
    opf.pool_index = 0;
    CTC_ERROR_GOTO(sys_usw_opf_init_offset(lchip, &opf, 0, MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM)), ret, error_proc);

    /* init asic table */
    sal_memset(&ds_linkagg_member, 0, sizeof(ds_linkagg_member));
    sal_memset(&lag_engine_timer_ctl0, 0, sizeof(lag_engine_timer_ctl0));

    core_frequecy = sys_usw_get_core_freq(lchip, 0);

    /* init dlb flow inactive timer, Tsunit =  updateThreshold0_f * (maxPtr0_f+1) / core_frequecy = 1ms */
    if(is_from_tmm)
    {
        uint32 value = 0;
        SetLagEngineTimerCtl(V, maxPhyPtr_f, &lag_engine_timer_ctl0, MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM) - 1);
        SetLagEngineTimerCtl(V, maxPtr_f, &lag_engine_timer_ctl0, MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM) - 1);
        SetLagEngineTimerCtl(V, minPtr_f, &lag_engine_timer_ctl0, 0);
        SetLagEngineTimerCtl(V, updateEn_f, &lag_engine_timer_ctl0, 1);
        SetLagEngineTimerCtl(V, tsThreshold_f, &lag_engine_timer_ctl0, SYS_DLB_TS_THRES);   /* ts unit is 1ms */
        SetLagEngineTimerCtl(V, updateThreshold_f, &lag_engine_timer_ctl0, (core_frequecy * 1000000 / 1000 / (SYS_DLB_MAX_PTR_TMM + 1)));    /* must big than 73 */

        cmd_timer = DRV_IOW(LagEngineTimerCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd_timer, &lag_engine_timer_ctl0), ret, error_proc);

        /* Config dlb flow pulse timer for Tp=1ms*/
        value = 40000000;   /* value = Tp /6.4ns * 256 */
        cmd = DRV_IOW(RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgRefDivLagEngineFlowSetActiveUpdatePulse_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &value), ret, error_proc);
        value = 0;
        cmd = DRV_IOW(RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgResetDivLagEngineFlowSetActiveUpdatePulse_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &value), ret, error_proc);
    }
    else
    {
        SetLagEngineTimerCtl0(V, maxPhyPtr0_f, &lag_engine_timer_ctl0, (MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM) - 1));
        SetLagEngineTimerCtl0(V, maxPtr0_f, &lag_engine_timer_ctl0, SYS_DLB_MAX_PTR);
        SetLagEngineTimerCtl0(V, minPtr0_f, &lag_engine_timer_ctl0, 0);
        SetLagEngineTimerCtl0(V, updateEn0_f, &lag_engine_timer_ctl0, 1);
        SetLagEngineTimerCtl0(V, tsThreshold0_f, &lag_engine_timer_ctl0, SYS_DLB_TS_THRES);   /* ts unit is 1ms */
        SetLagEngineTimerCtl0(V, updateThreshold0_f, &lag_engine_timer_ctl0, (core_frequecy * 1000000 / 1000 / (SYS_DLB_MAX_PTR + 1)));    /* must big than 73 */

        cmd_timer = DRV_IOW(LagEngineTimerCtl0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd_timer, &lag_engine_timer_ctl0), ret, error_proc);

        sal_memset(&lag_engine_timer_ctl0, 0, sizeof(lag_engine_timer_ctl0));
        SetLagEngineTimerCtl1(V, maxPhyPtr1_f, &lag_engine_timer_ctl0, (MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_ALL_MEM_NUM)-1));
        SetLagEngineTimerCtl1(V, maxPtr1_f, &lag_engine_timer_ctl0, SYS_DLB_MAX_PTR);
        SetLagEngineTimerCtl1(V, minPtr1_f, &lag_engine_timer_ctl0, 0);
        SetLagEngineTimerCtl1(V, updateEn1_f, &lag_engine_timer_ctl0, 1);
        SetLagEngineTimerCtl1(V, tsThreshold1_f, &lag_engine_timer_ctl0, SYS_DLB_TS_THRES);   /* ts unit is 1ms */
        SetLagEngineTimerCtl1(V, updateThreshold1_f, &lag_engine_timer_ctl0,      /* must big than 73 */
            (core_frequecy * 1000000 / 1000 / (SYS_DLB_MAX_PTR+1)));

        cmd_timer = DRV_IOW(LagEngineTimerCtl1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd_timer, &lag_engine_timer_ctl0), ret, error_proc);
    }
#ifndef EMULATION_ENV
    /* init port linkagg member info */
    sys_usw_get_gchip_id(lchip, &gchip);
    mem_idx = MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM);
    cmd_linkagg = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
    SetDsLinkAggregateMember(V, destChipId_f, &ds_linkagg_member, gchip);
    SetDsLinkAggregateMember(V, destChannelId_f, &ds_linkagg_member, 0);
    for (index = 0; index < mem_idx; index++)
    {
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd_linkagg, &ds_linkagg_member), ret, error_proc);
    }
#endif
    /* init channel linkagg port info */
    cmd = DRV_IOW(MetFifoCtl_t, MetFifoCtl_chanLagEnable_f);
    field_val = 1;
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val), ret, error_proc);

#ifndef EMULATION_ENV
    cmdr_chan_port = DRV_IOR(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    cmd_chan_port = DRV_IOW(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    for (index = 0; index < SYS_USW_MAX_PORT_NUM_PER_CHIP; index++)
    {
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmdr_chan_port, &ds_linkagg_port), ret, error_proc);
        SetDsPortChannelLag(V, linkAggregationChannelGroup_f, &ds_linkagg_port, 0);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd_chan_port, &ds_linkagg_port), ret, error_proc);
    }
#endif
    /*clear MemberBitmap and BlockMask for mc*/
    if(DRV_FROM_TMM(lchip))
    {
        sys_usw_dmps_port_info_t dmps_port_info = {0};
#ifndef EMULATION_ENV
        DsMetNonUcLagMemberBitmap_m  member_bitmap;
        sal_memset(&member_bitmap, 0x0, sizeof(DsMetNonUcLagMemberBitmap_m));
        for (index = 0; index < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM); index++)
        {
            cmd = DRV_IOW(DsMetNonUcLagMemberBitmap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &member_bitmap), ret, error_proc);
        }

        cmd = DRV_IOW(DsMetNonUcLagBlockMask_t, DsMetNonUcLagBlockMask_blockPbmMask_f);
        for (index = 0; index < SYS_LINKAGG_LB_HASH_MAX * 4; index++)
        {
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &block_mask), ret, error_proc);
        }
#endif
        cmd_chan_port = DRV_IOW(DsMetPortLagLinkSelfHealingSet_t, DsMetPortLagLinkSelfHealingSet_channelId_f);
        for (index = 0; index < MCHIP_CAP(SYS_CAP_PORT_NUM); index++)
        {
            dmps_port_info.gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, index);
            CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &field_val), ret, error_proc);
            field_val = SYS_USW_CHANNEL_ENCODE(field_val); /* for TMG, chan bit7 is dpid, bit6 is not use */
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd_chan_port, &field_val), ret, error_proc);
        }
        if (DRV_FROM_AT(lchip))
        {
            cmd_chan_port = DRV_IOW(DsMetExcpPortLagLinkSelfHealingSet_t, DsMetExcpPortLagLinkSelfHealingSet_channelId_f);
            for (index = 0; index < MCHIP_CAP(SYS_CAP_PORT_NUM); index++)
            {
                dmps_port_info.gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, index);
                CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &field_val), ret, error_proc);
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd_chan_port, &field_val), ret, error_proc);
            }
        }
#ifndef EMULATION_ENV
        /*channel linkagg*/
        cmd = DRV_IOW(DsMetNonUcChanLagBlockMask_t, DsMetNonUcChanLagBlockMask_chanBlockBitmap_f);
        for (index = 0; index < SYS_LINKAGG_CHAN_HASH_MAX; index++)
        {
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index, cmd, &block_mask), ret, error_proc);
        }
#endif
        sys_usw_dma_get_dma_memory(lchip, 0, &p_dma_mem);
        if (p_dma_mem)
        {
            uint32* p_dma_mem_tmp = NULL;
            for (index = 0; (index < SYS_LINKAGG_LB_HASH_MAX); index++)
            {
                p_dma_mem_tmp = (uint32*)((uint8*)p_dma_mem + index*TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t));
                cmd = DRV_IOR(DsMetNonUcLagBlockMask_t, DsMetNonUcLagBlockMask_blockPbmMask_f);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, p_dma_mem_tmp));
            }
        }
    }

    /* the first mirror dest member need init to DROP */
    if (DRV_FROM_AT(lchip))
    {
        DsMetFifoExcpLinkAggregation_m ds_excp_linkagg;
        sal_memset(&ds_excp_linkagg, 0, sizeof(ds_excp_linkagg));
        SetDsMetFifoExcpLinkAggregation(V, g_0_destId_f, &ds_excp_linkagg, MCHIP_CAP(SYS_CAP_RSV_PORT_DROP_ID));
        cmd = DRV_IOW(DsMetFifoExcpLinkAggregation_t, DRV_ENTRY_FLAG);
        for (index = 0; index < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM); index++)
        {
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &ds_excp_linkagg), ret, error_proc);
        }
    }


    p_usw_linkagg_master[lchip]->chan_group = ctc_vector_init(8, CTC_VEC_BLOCK_NUM(MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1, 8));
    if (NULL == p_usw_linkagg_master[lchip]->chan_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Allocate vector for chanagg fail!\n");
        ret = CTC_E_NO_MEMORY;
        goto error_proc;
    }

    /* init hw sync */
    sal_memset(&lag_engine_ctl, 0, sizeof(lag_engine_ctl));
    cmd = DRV_IOR(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl), ret, error_proc);

    SetLagEngineCtl(V, linkChangeEn_f, &lag_engine_ctl, 1);
    SetLagEngineCtl(V, lagGroupMemoryBase_f, &lag_engine_ctl, MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
    SetLagEngineCtl(V, lbMode0SupportLinkSelfHealing0_f, &lag_engine_ctl, 1);
    SetLagEngineCtl(V, lbMode0SupportLinkSelfHealing1_f, &lag_engine_ctl, 1);
    SetLagEngineCtl(V, lbMode4SupportLinkSelfHealing0_f, &lag_engine_ctl, 1);
    SetLagEngineCtl(V, lbMode4SupportLinkSelfHealing1_f, &lag_engine_ctl, 1);
    SetLagEngineCtl(V, chanBandwidthShift0_f, &lag_engine_ctl, 9);
    SetLagEngineCtl(V, chanBandwidthShift1_f, &lag_engine_ctl, 9);
    SetLagEngineCtl(V, lagMode_f, &lag_engine_ctl, 0);
    SetLagEngineCtl(V, antFlowHashOffsetCfg_f, &lag_engine_ctl, 0);
    SetLagEngineCtl(V, antFlowHashSelectCfg_f, &lag_engine_ctl, MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM) == SYS_USW_LB_HASH_CTL_NUM ? 2 : 1);
    SetLagEngineCtl(V, chipCode_f, &lag_engine_ctl, 0); /*0:gg2 1:gg2+ 2:m6 3:m7*/
    SetLagEngineCtl(V, portLagLshEn_f, &lag_engine_ctl, 15);
    SetLagEngineCtl(V, portLagLshHashOffsetCfg_f, &lag_engine_ctl, 0);
    SetLagEngineCtl(V, portLagLshHashSelectCfg_f, &lag_engine_ctl, MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM) == SYS_USW_LB_HASH_CTL_NUM ? 2 : 1);
    SetLagEngineCtl(V, d2dInterConnectEn_f, &lag_engine_ctl, 1);

    cmd = DRV_IOW(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl), ret, error_proc);

    field_val = 1;
    cmd = DRV_IOW(IpeHeaderAdjustCtl_t, IpeHeaderAdjustCtl_fromCpuForceHdrHashValid_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val), ret, error_proc);

    /* init LagEngineDreTimerCtl_t for dlb */
    CTC_ERROR_GOTO(_sys_usw_lag_engine_dlb_init(lchip), ret, error_proc);
#if 0
    if (DRV_FROM_TMM(lchip) && (CTC_WB_STATUS(lchip) != CTC_WB_STATUS_RELOADING) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
    {
        CTC_ERROR_GOTO(_sys_usw_linkagg_init_loop_chan_lag(lchip), ret, error_proc);
    }
#endif
    sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_CHAN_LINKDOWN_SCAN, sys_usw_linkagg_failover_isr);

    /* set chip_capability*/
    MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM) = linkagg_num;
    MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_DLB_GROUP_NUM) = linkagg_num;
    flow_num = is_from_tmm ? MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM) : MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM);
    if (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX)
    {
        MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_MEMBER_NUM) = MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM);
        MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_DLB_FLOW_NUM) = flow_num;
    }
    else
    {
        MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_MEMBER_NUM) = MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM) / linkagg_num;
        MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_DLB_FLOW_NUM) = flow_num / linkagg_num;
    }

    /* warmboot register */
    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_LINKAGG,SYS_WB_APPID_LINKAGG_SUBID_MAX, sys_usw_linkagg_wb_sync), ret, error_proc);

    /* dump-db register */
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_LINKAGG, sys_usw_linkagg_dump_db), ret, error_proc);

    /* warmboot data restore */
    if (CTC_WB_ENABLE(lchip) && (CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        CTC_ERROR_GOTO(sys_usw_linkagg_wb_restore(lchip), ret, error_proc);
    }

    if (CTC_WB_ENABLE(lchip))
    {
        _sys_usw_linkagg_wb_init(lchip);
    }
    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_LINKAGG);
    return CTC_E_NONE;

error_proc:
    if (NULL != p_usw_linkagg_master[lchip])
    {
        if (0 != p_usw_linkagg_master[lchip]->opf_type)
        {
            sys_usw_opf_deinit(lchip, p_usw_linkagg_master[lchip]->opf_type);
        }

        if (NULL != p_usw_linkagg_master[lchip]->chan_group)
        {
            /*free chanagg data*/
            ctc_vector_traverse(p_usw_linkagg_master[lchip]->chan_group, (vector_traversal_fn)_sys_usw_linkagg_free_node_data, (void*)&lchip);

            ctc_vector_release(p_usw_linkagg_master[lchip]->chan_group);
        }

        if (NULL != p_usw_linkagg_master[lchip]->group_vector)
        {
            /*free linkagg*/
            ctc_vector_traverse(p_usw_linkagg_master[lchip]->group_vector, (vector_traversal_fn)_sys_usw_linkagg_free_node_data, (void*)&lchip);

            ctc_vector_release(p_usw_linkagg_master[lchip]->group_vector);
        }

        if (NULL != p_usw_linkagg_master[lchip]->p_linkagg_mutex)
        {
            sal_mutex_destroy(p_usw_linkagg_master[lchip]->p_linkagg_mutex);
        }

        mem_free(p_usw_linkagg_master[lchip]);
    }
    return ret;
}

int32
sys_usw_linkagg_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_LINKAGG,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_LINKAGG, NULL);
    sys_usw_interrupt_register_isr(lchip, SYS_INTR_FUNC_CHAN_LINKDOWN_SCAN, NULL);
    if (NULL != p_usw_linkagg_master[lchip])
    {
        SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_linkagg_master, CTC_FEATURE_LINKAGG);
        if (0 != p_usw_linkagg_master[lchip]->opf_type)
        {
            sys_usw_opf_deinit(lchip, p_usw_linkagg_master[lchip]->opf_type);
        }

        if (NULL != p_usw_linkagg_master[lchip]->chan_group)
        {
            /*free chanagg data*/
            ctc_vector_traverse(p_usw_linkagg_master[lchip]->chan_group, (vector_traversal_fn)_sys_usw_linkagg_free_node_data, (void*)&lchip);

            ctc_vector_release(p_usw_linkagg_master[lchip]->chan_group);
        }

        if (NULL != p_usw_linkagg_master[lchip]->group_vector)
        {
            /*free linkagg*/
            ctc_vector_traverse(p_usw_linkagg_master[lchip]->group_vector, (vector_traversal_fn)_sys_usw_linkagg_free_node_data, (void*)&lchip);

            ctc_vector_release(p_usw_linkagg_master[lchip]->group_vector);
        }

        if (NULL != p_usw_linkagg_master[lchip]->p_linkagg_mutex)
        {
            sal_mutex_destroy(p_usw_linkagg_master[lchip]->p_linkagg_mutex);
        }

        mem_free(p_usw_linkagg_master[lchip]);
    }

    return CTC_E_NONE;
}

/**
 @brief The function is to set linkagg property
*/
int32
sys_usw_linkagg_set_property(uint8 lchip, uint16 tid, ctc_linkagg_property_t linkagg_prop, uint32 value)
{
    uint32 cmd_group = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DsLinkAggregateGroup_m ds_linkagg_group;
    sys_linkagg_t*  p_group = NULL;
    sys_linkagg_t*  p_chan_group = NULL;
    uint16 tid_buf = tid;
    uint32 member_list[SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX] = {0};
    uint8 gchip = 0;
    uint8  member_cnt_new = 0;
    /* sanity check */
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid_buf);
    if ((CTC_LINKAGG_PROP_LB_HASH_OFFSET == linkagg_prop) || (CTC_LINKAGG_PROP_LMPF_LB_HASH_OFFSET == linkagg_prop) || (CTC_LINKAGG_PROP_SPM_HASH_OFFSET == linkagg_prop))
    {
        SYS_USW_LB_HASH_CHK_OFFSET(value);
    }

    LINKAGG_LOCK;
    /*channel lag*/
    p_chan_group = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, tid_buf);
    if ((p_chan_group) && (linkagg_prop == CTC_LINKAGG_PROP_LB_HASH_OFFSET))
    {
        CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_set_channel_property(lchip, tid_buf, value),p_usw_linkagg_master[lchip]->p_linkagg_mutex);
        LINKAGG_UNLOCK;
        return CTC_E_NONE;
    }
    /* check exist */
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg is not exist!\n");
        CTC_ERROR_RETURN_WITH_UNLOCK(CTC_E_NOT_EXIST, p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    }

    if(!DRV_FROM_TMM(lchip) && (linkagg_prop == CTC_LINKAGG_PROP_LMPF_LB_HASH_OFFSET || linkagg_prop == CTC_LINKAGG_PROP_LMPF_CANCEL)) 
    {
        tid_buf = MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM) + tid;
    }
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_IOCTL(lchip, tid_buf, cmd_group, &ds_linkagg_group), p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    switch(linkagg_prop)
    {
        case CTC_LINKAGG_PROP_LB_HASH_OFFSET:
        case CTC_LINKAGG_PROP_LMPF_LB_HASH_OFFSET:
            SetDsLinkAggregateGroup(V, hashOffset_f, &ds_linkagg_group, value % 16);
            SetDsLinkAggregateGroup(V, hashSelect_f, &ds_linkagg_group, value / 16);
            break;
        case CTC_LINKAGG_PROP_SPM_HASH_OFFSET:
            SetDsLinkAggregateGroup(V, antFlowHashOffset_f, &ds_linkagg_group, value % 16);
            SetDsLinkAggregateGroup(V, antFlowHashSelect_f, &ds_linkagg_group, value / 16);
            break;
        case CTC_LINKAGG_PROP_LMPF_CANCEL:
            if (0 == p_group->cfg_lmpf)
            {
                CTC_ERROR_RETURN_WITH_UNLOCK(CTC_E_NOT_SUPPORT, p_usw_linkagg_master[lchip]->p_linkagg_mutex);
            }
            p_group->flag = value?(p_group->flag & ~CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST):(p_group->flag | CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST);
            if (!DRV_FROM_TMM(lchip))
            {
                p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid_buf);
                if(!p_group)
                {
                    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg is not exist!\n");
                    CTC_ERROR_RETURN_WITH_UNLOCK(CTC_E_NOT_EXIST, p_usw_linkagg_master[lchip]->p_linkagg_mutex);
                }
                p_group->flag = value?(p_group->flag & ~CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST):(p_group->flag | CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST);
                SetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_linkagg_group, (value ? 0: p_group->real_member_num));
            }
            else
            {
                uint32 i     = 0;
                if (value)/*add*/
                {
                    p_group->real_member_num = 0;
                    for (i = 0; i<p_group->port_cnt; i++)
                    {
                        gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_group->port_list[i]->gport);
                        if (!sys_usw_chip_is_local(lchip, gchip) && \
                        (CTC_LINKAGG_MODE_STATIC_FAILOVER == p_group->mode || CTC_LINKAGG_MODE_DLB == p_group->mode))
                        {
                           continue;
                        }
                        CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_add_port_hw(lchip, p_group, p_group->port_list[i]->gport, 0), p_usw_linkagg_master[lchip]->p_linkagg_mutex);
                    }
                }
                else if (p_group->local_port_cnt) /*remove*/
                {
                    p_group->real_member_num = 0;
                    for (i = 0; i < p_group->port_cnt ; i++ )
                    {
                        if(p_group->port_list[i]->is_local)
                        {
                            gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_group->port_list[i]->gport);
                            if (!sys_usw_chip_is_local(lchip, gchip) && \
                             (CTC_LINKAGG_MODE_STATIC_FAILOVER == p_group->mode || CTC_LINKAGG_MODE_DLB == p_group->mode))
                            {
                                continue;
                            }
                            CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_add_port_hw(lchip, p_group, p_group->port_list[i]->gport, 0), p_usw_linkagg_master[lchip]->p_linkagg_mutex);
                        }
                    }
                }
                if (p_group->mirror_ref_cnt)
                {
                   member_cnt_new = SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX;
                   CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_get_ports2(lchip, p_group, member_list, &member_cnt_new),p_usw_linkagg_master[lchip]->p_linkagg_mutex);
                   SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, member_list, member_cnt_new, 1);
                }
                if(MCHIP_LAG(lchip)->update_mirror_dest)
                {
                    CTC_ERROR_RETURN_WITH_UNLOCK(MCHIP_LAG(lchip)->update_mirror_dest(lchip, tid, 1),p_usw_linkagg_master[lchip]->p_linkagg_mutex);
                }

                LINKAGG_UNLOCK;
                return CTC_E_NONE;
            }
            break;
        default :
            break;
    }
    cmd_group = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_IOCTL(lchip, tid_buf, cmd_group, &ds_linkagg_group), p_usw_linkagg_master[lchip]->p_linkagg_mutex);

    LINKAGG_UNLOCK;
    return CTC_E_NONE;
}

/**
 @brief The function is to get linkagg property
*/
int32
sys_usw_linkagg_get_property(uint8 lchip, uint16 tid, ctc_linkagg_property_t linkagg_prop, uint32* p_value)
{
    uint8 value = 0;
    uint32 cmd_group = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DsLinkAggregateGroup_m ds_linkagg_group;
    sys_linkagg_t*  p_group = NULL;
    uint16 tid_buf = tid;

    /* sanity check */
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid_buf);
    CTC_PTR_VALID_CHECK(p_value);
    LINKAGG_LOCK;
    /* check exist */
    if(!DRV_FROM_TMM(lchip))
    {
        tid_buf = CTC_LINKAGG_PROP_LB_HASH_OFFSET == linkagg_prop ? tid_buf : MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM) + tid_buf;
    }
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid_buf);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg is not exist!\n");
        CTC_ERROR_RETURN_WITH_UNLOCK(CTC_E_NOT_EXIST, p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    }
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_IOCTL(lchip, tid_buf, cmd_group, &ds_linkagg_group), p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    switch(linkagg_prop)
    {
        case CTC_LINKAGG_PROP_LB_HASH_OFFSET:
        case CTC_LINKAGG_PROP_LMPF_LB_HASH_OFFSET:
            value = GetDsLinkAggregateGroup(V, hashSelect_f, &ds_linkagg_group);
            value = (value<<4) + GetDsLinkAggregateGroup(V, hashOffset_f, &ds_linkagg_group);
            break;
        case CTC_LINKAGG_PROP_SPM_HASH_OFFSET:
            value = GetDsLinkAggregateGroup(V, antFlowHashSelect_f, &ds_linkagg_group);
            value = (value<<4) + GetDsLinkAggregateGroup(V, antFlowHashOffset_f, &ds_linkagg_group);
            break;
        case CTC_LINKAGG_PROP_LMPF_CANCEL:
            if (0 == p_group->cfg_lmpf)
            {
                CTC_ERROR_RETURN_WITH_UNLOCK(CTC_E_NOT_SUPPORT, p_usw_linkagg_master[lchip]->p_linkagg_mutex);
            }

            value = (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)?0:1;
            break;
        default :
            break;
    }
    *p_value = value;
    LINKAGG_UNLOCK;
    return CTC_E_NONE;
}

/**
 @brief The function is to create one linkagg
*/
int32
sys_usw_linkagg_create(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp)
{
    uint16 mem_idx = 0;
    uint16  tid = 0;
    uint32 cmd_group = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    int32  ret = CTC_E_NONE;
    uint32 mem_num = 0;
    uint32 mem_base = 0;
    uint32 antflow_base = 0;
    DsLinkAggregateGroup_m ds_linkagg_group;
    sys_linkagg_t* p_group = NULL;
    uint8 before_tm = DRV_IS_DUET2(lchip)|| DRV_IS_TSINGMA(lchip);

    /* sanity check */
    SYS_LINKAGG_INIT_CHECK();
    CTC_ERROR_RETURN(_sys_usw_linkagg_group_param_check(lchip, p_linkagg_grp));

    /* do create */
    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP, 1);
    tid = p_linkagg_grp->tid;
    /* check exist */
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Has Exist!\n");
        ret = CTC_E_EXIST;
        goto error_proc;
    }

     if(!before_tm && (p_linkagg_grp->linkagg_mode == CTC_LINKAGG_MODE_STATIC_FAILOVER))
     {
        p_linkagg_grp->linkagg_mode = CTC_LINKAGG_MODE_STATIC;
        p_linkagg_grp->lsh_mode = CTC_LINKAGG_LSH_MODE_NEXT;
     }


    sal_memset(&ds_linkagg_group, 0, sizeof(ds_linkagg_group));

    if (((p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) || CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)) && before_tm)
    {
        sys_linkagg_t* p_lmpf_group = NULL;

        CTC_ERROR_GOTO(_sys_usw_linkagg_add_db(lchip, tid + MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM), p_linkagg_grp, &p_lmpf_group), ret, error_proc);
        p_lmpf_group->tid = CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)?tid:p_lmpf_group->tid;
        SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, 4);
        SetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_linkagg_group, p_lmpf_group->member_base);
        SetDsLinkAggregateGroup(V, hashOffset_f, &ds_linkagg_group, 0);
        SetDsLinkAggregateGroup(V, hashSelect_f, &ds_linkagg_group, MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM) == SYS_USW_LB_HASH_CTL_NUM ? 2 : 1);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_lmpf_group->tid, cmd_group, &ds_linkagg_group), ret, error_1);
        p_lmpf_group->cfg_lmpf = 1;
    }
    else if (CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
    {
        sys_linkagg_t* p_lmpf_group = NULL;
        CTC_ERROR_GOTO(_sys_usw_linkagg_add_db(lchip, tid + MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM), p_linkagg_grp, &p_lmpf_group), ret, error_proc);
        p_lmpf_group->tid = tid;
    }

    CTC_ERROR_GOTO(_sys_usw_linkagg_add_db(lchip, tid, p_linkagg_grp, &p_group), ret, error_0);
    if (CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && before_tm)
    {
        p_group->tid = tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM);
    }

    mem_base = p_group->member_base;
    mem_num = p_group->max_member_num;
    SetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_linkagg_group, mem_base);
    SetDsLinkAggregateGroup(V, hashOffset_f, &ds_linkagg_group, 0);
    SetDsLinkAggregateGroup(V, hashSelect_f, &ds_linkagg_group, MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM) == SYS_USW_LB_HASH_CTL_NUM ? 2 : 1);
    if(DRV_FROM_TMM(lchip) && (p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN))
    {
        CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset(lchip, DsAntFlow_t, 0, p_linkagg_grp->flow_num, 1, &antflow_base), ret, error_1);

        SetDsLinkAggregateGroup(V, antFlowEn_f, &ds_linkagg_group, 1);
        SetDsLinkAggregateGroup(V, antFlowHashOffset_f, &ds_linkagg_group, 0);
        SetDsLinkAggregateGroup(V, antFlowHashSelect_f, &ds_linkagg_group, MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM) == SYS_USW_LB_HASH_CTL_NUM ? 2 : 1);
        SetDsLinkAggregateGroup(V, antFlowTableBase_f, &ds_linkagg_group, antflow_base >> SYS_LINKAGG_SPM_TBL_BASE_WIDTH);
        SetDsLinkAggregateGroup(V, linkAggFlowNum_f, &ds_linkagg_group, _sys_usw_linkagg_flows2driver(lchip, p_linkagg_grp->flow_num, 1));
        CTC_ERROR_GOTO(_sys_usw_linkagg_clear_flow_active(lchip, p_group->tid, 1, antflow_base, p_linkagg_grp->flow_num), ret, error_1);
    }

    switch (p_linkagg_grp->linkagg_mode)
    {
        case CTC_LINKAGG_MODE_STATIC:
        case CTC_LINKAGG_MODE_STATIC_FAILOVER:
        {
            if (p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
            {
                SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, 4);
            }
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_group->tid, cmd_group, &ds_linkagg_group), ret, error_1);
            break;
        }
        case CTC_LINKAGG_MODE_RR:
        {
            uint8 rr_profile_id = _sys_usw_linkagg_find_rr_profile_id(lchip, tid);
            DsLinkAggregateRrCount_m ds_linkagg_rr;
            LagRrProfileIdMappingCtl_m lag_rrprofile;
            uint32 cmd_rr = DRV_IOW(DsLinkAggregateRrCount_t, DRV_ENTRY_FLAG);
            uint32 cmd_rrf = DRV_IOW(LagRrProfileIdMappingCtl_t, DRV_ENTRY_FLAG);

            if (rr_profile_id >= 16)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] rr mod is invalid,because it greater than 15 \n");
                ret = CTC_E_NO_RESOURCE;
                goto error_1;
            }

            sal_memset(&ds_linkagg_rr, 0, sizeof(ds_linkagg_rr));
            sal_memset(&lag_rrprofile, 0, sizeof(lag_rrprofile));
            if (p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_RANDOM_RR)
            {
                SetDsLinkAggregateRrCount(V, randomRrEn_f, &ds_linkagg_rr, 1);
            }
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, rr_profile_id, cmd_rr, &ds_linkagg_rr), ret, error_1);

            SetLagRrProfileIdMappingCtl(V, rrProfileId_f, &lag_rrprofile, rr_profile_id);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_group->tid, cmd_rrf, &lag_rrprofile), ret, error_1);

            SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, 2);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_group->tid, cmd_group, &ds_linkagg_group), ret, error_1);
            CTC_BIT_SET(p_usw_linkagg_master[lchip]->rr_profile_bmp, rr_profile_id);
            break;
        }
        case CTC_LINKAGG_MODE_DLB:
        {
            uint32 cmd_w = 0;
            uint8 gchip = 0;
            uint32 field_val = 0;

            SetDsLinkAggregateGroup(V, linkAggFlowNum_f, &ds_linkagg_group, _sys_usw_linkagg_flows2driver(lchip, mem_num, 0));
            SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_group->tid, cmd_group, &ds_linkagg_group), ret, error_1);

            /* init DsLinkAggregateMember_t or DsLagDlbFlowSetTable chipid */
            cmd_w = before_tm ? DRV_IOW(DsLinkAggregateMember_t, DsLinkAggregateMember_destChipId_f)
                              : DRV_IOW(DsLagDlbFlowSetTable_t, DsLagDlbFlowSetTable_destChipId_f) ;
            CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip), ret, error_1);
            field_val = gchip;
            for (mem_idx = mem_base; mem_idx < (mem_base + mem_num); mem_idx++)
            {
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, mem_idx, cmd_w, &field_val), ret, error_1);
            }

            /* flush all DsLinkAggregateMember_t or DsLagDlbFlowSetTable_t to reverve channel for dlb mode */
            CTC_ERROR_GOTO(_sys_usw_linkagg_reverve_member(lchip, p_group->tid, 0), ret, error_1);
            break;
        }
        default:
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "linkagg group mode error!\n");

            ret = CTC_E_NOT_SUPPORT;
            goto error_1;
        }
    }
    p_group->cfg_lmpf = (p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) ? 1:0;

    LINKAGG_UNLOCK;

    CTC_ERROR_DUMP(sys_usw_brguc_nh_create(lchip, CTC_MAP_TID_TO_GPORT(tid), CTC_NH_PARAM_BRGUC_SUB_TYPE_BASIC));
    sys_usw_l2_set_dsmac(lchip, CTC_MAP_TID_TO_GPORT(tid),TRUE);

    return CTC_E_NONE;

error_1:
    if(p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN)
    {
        sys_usw_ftm_free_table_offset(lchip, DsAntFlow_t, 0, p_linkagg_grp->flow_num, antflow_base);
    }
error_0:
    if (((p_linkagg_grp->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)&& before_tm) || CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
    {
        _sys_usw_linkagg_remove_db(lchip, tid + MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
    }
    _sys_usw_linkagg_remove_db(lchip, tid);
error_proc:
    LINKAGG_UNLOCK;
    return ret;
}

/**
 @brief The function is to delete one linkagg
*/
int32
sys_usw_linkagg_destroy(uint8 lchip, uint16 tid)
{
    int32  ret = CTC_E_NONE;
    uint8  step = 0;
    uint16 mem_idx = 0;
    uint16 mem_num = 0;
    uint16 mem_base = 0;
    uint32 cmd = 0;
    uint32 cmd_member = 0;
    uint32 cmd_memberset = 0;
    DsLinkAggregateGroup_m ds_linkagg_group;
    DsLinkAggregateMember_m ds_linkagg_member;
    DsLinkAggregateMemberSet_m ds_linkagg_memberset;
    sys_linkagg_t* p_group = NULL;
    uint8  gchip_id = 0;
    uint16 destId = 0;
    uint32 gport_temp = 0;
    uint32* gports = NULL;
    uint32 cnt = 0;
    uint16 index = 0;
    uint8  mirror_ref_cnt = 0;

    /*sanity check*/
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "linkAggId = 0x%x\n", tid);

    sal_memset(&ds_linkagg_group, 0, sizeof(ds_linkagg_group));
    sal_memset(&ds_linkagg_member, 0, sizeof(ds_linkagg_member));

    /*do remove*/
    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto out;
    }

    mirror_ref_cnt = p_group->mirror_ref_cnt;
    if (MCHIP_LAG(lchip)->destroy)
    {
        ret = MCHIP_LAG(lchip)->destroy(lchip, p_group);
        LINKAGG_UNLOCK;
        if (ret == CTC_E_NONE && mirror_ref_cnt)
        {
            SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, NULL, 0, 0);
        }
        return ret;
    }
    p_group->is_lag = 0;
    MALLOC_ZERO(MEM_LINKAGG_MODULE, gports,p_group->max_member_num*sizeof(uint32));
    if(NULL == gports && p_group->max_member_num)
    {
        ret = CTC_E_NO_MEMORY;
        goto out;
    }
    /*for static fail over, real member num may be changed, must reriver*/
    if(p_group->mode == CTC_LINKAGG_MODE_STATIC_FAILOVER)
    {
        p_group->real_member_num = _sys_usw_dlb_get_real_member_num(lchip, p_group->tid);
    }

    mem_base = p_group->member_base;
    mem_num =p_group->max_member_num? p_group->real_member_num:0;

    if (mem_num > 0)
    {
        switch (p_group->mode)
        {
            case CTC_LINKAGG_MODE_STATIC:
            case CTC_LINKAGG_MODE_STATIC_FAILOVER:
            case CTC_LINKAGG_MODE_RR:
            {
                cmd_member = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);

                for (mem_idx = mem_base; mem_idx < (mem_base + mem_num); mem_idx++)
                {
                    CTC_ERROR_GOTO(DRV_IOCTL(lchip, mem_idx, cmd_member, &ds_linkagg_member), ret, out);
                    gchip_id = GetDsLinkAggregateMember(V, destChipId_f, &ds_linkagg_member);
                    destId = GetDsLinkAggregateMember(V, destId_f, &ds_linkagg_member);
                    gport_temp = CTC_MAP_LPORT_TO_GPORT(gchip_id, destId);
                    gports[cnt] = gport_temp;
                    cnt++;
                }
                break;
            }
            case CTC_LINKAGG_MODE_DLB:
            {
                /*dlb only support local member, get gchip from lchip*/

                cmd_memberset = DRV_IOR(DsLinkAggregateMemberSet_t, DRV_ENTRY_FLAG);
                CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_group->tid, cmd_memberset, &ds_linkagg_memberset), ret, out);
                CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip_id), ret, out);
                step = DsLinkAggregateMemberSet_array_1_channelId_f - DsLinkAggregateMemberSet_array_0_channelId_f;
                for (mem_idx = mem_base; mem_idx < (mem_base + mem_num); mem_idx++)
                {
                    destId = GetDsLinkAggregateMemberSet(V, array_0_localPhyPort_f + (mem_idx - mem_base) * step, &ds_linkagg_memberset);
                    gport_temp = CTC_MAP_LPORT_TO_GPORT(gchip_id, destId);
                    gports[cnt] = gport_temp;
                    cnt++;
                }
                break;
            }
            default:
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "linkagg group mode error!\n");
                ret = CTC_E_NOT_SUPPORT;
                goto out;
            }
        }
    }

    for (index = 0; index < cnt; index++)
    {
        if (p_group->mode == CTC_LINKAGG_MODE_DLB)
        {
            CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port_hw(lchip, p_group, gports[index], 0), ret, out);
        }
        if (TRUE == sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(gports[index])))
        {
            /*update mcast linkagg bitmap*/
            CTC_ERROR_GOTO(sys_usw_port_api_update_mc_linkagg(lchip, p_group->tid%MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM), CTC_MAP_GPORT_TO_LPORT(gports[index]), 0), ret, out);
            /*set local port's global_port*/
            if (!p_usw_linkagg_master[lchip]->bind_gport_disable)
            {
                CTC_ERROR_GOTO(sys_usw_port_api_set_global_port(lchip, CTC_MAP_GPORT_TO_LPORT(gports[index]), gports[index], FALSE), ret, out);
            }
        }
    }

    if (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
    {
        sys_linkagg_t* p_nonuc_group = NULL;
        uint32 member_port = 0;
        p_nonuc_group  = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
        if (NULL == p_nonuc_group)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Has not Exist!\n");
            ret = CTC_E_NOT_EXIST;
            goto out;
        }
        for (mem_idx = 0; mem_idx < p_nonuc_group->port_cnt; mem_idx++)
        {
            if(!p_nonuc_group->port_list[mem_idx])
            {
                continue;
            }
            member_port = p_nonuc_group->port_list[mem_idx]->gport;
            if (TRUE == sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(member_port)))
            {
                sys_usw_port_api_update_mc_linkagg(lchip, p_nonuc_group->tid, CTC_MAP_GPORT_TO_LPORT(member_port), 0);
            }
        }
    }

    /*reset linkagg group */
    cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &ds_linkagg_group), ret, out);
    CTC_ERROR_GOTO(sys_usw_l2_set_dsmac(lchip, CTC_MAP_TID_TO_GPORT(tid), FALSE), ret, out);
    if(p_group->mode == CTC_LINKAGG_MODE_RR)
    {
        uint32 rr_profile_id = 0;
        cmd = DRV_IOR(LagRrProfileIdMappingCtl_t, LagRrProfileIdMappingCtl_rrProfileId_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, tid, cmd, &rr_profile_id), ret,  out);
        CTC_BIT_UNSET(p_usw_linkagg_master[lchip]->rr_profile_bmp, rr_profile_id);
    }
    if ((p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) || (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)))
    {
        cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid + MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM), cmd, &ds_linkagg_group), ret, out);
        _sys_usw_linkagg_remove_db(lchip, tid + MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
    }

    _sys_usw_linkagg_remove_db(lchip, tid);
out:
    LINKAGG_UNLOCK;
    sys_usw_brguc_nh_delete(lchip, CTC_MAP_TID_TO_GPORT(tid));
    if(gports)
    {
        mem_free(gports);
    }
    /*useless for TMM end*/
    return ret;
}

STATIC int32
_sys_usw_linkagg_check_link_stats(uint8 lchip)
{
    uint32  cmdr1 = DRV_IOR(LinkAggLinkScanInfo_t, LinkAggLinkScanInfo_linkDownScanState_f);
    uint32  cmdr2 = DRV_IOR(LinkAggState_t, LinkAggState_curLinkScanState_f);
    uint32  link_stats[2] = {0};
    uint32  idle = 0;
    uint16  wait_cnt = 0;

    do
    {
        DRV_FIELD_IOCTL(lchip, 0, cmdr1, link_stats);
        DRV_FIELD_IOCTL(lchip, 0, cmdr2, &idle);
        if (!link_stats[0] && !link_stats[1] && !idle)
        {
            break;
        }

        sal_task_sleep(1);
        wait_cnt++;

    }while(wait_cnt < 0x1000);

    DRV_FIELD_IOCTL(lchip, 0, cmdr1, link_stats);
    if ((link_stats[0] != 0) || (link_stats[1] != 0))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Chip is processing, processing channel: 0x%x-0x%x\n", link_stats[1],link_stats[0]);
        return 1;
    }

    DRV_FIELD_IOCTL(lchip, 0, cmdr2, &idle);
    if(idle != 0)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Chip stats is not idle, can not add/remove port\n");
        return 1;
    }

    return 0;
}
#if 0
STATIC int32
_sys_usw_linkagg_update_backup_ports(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 is_add)
{
    int32 ret = 0;
    uint16 loop1 = 0;
    uint16 loop2 = 0;
    ctc_linkagg_failover_t failover = {0};

    failover.backup_ports = (uint32*)mem_malloc(MEM_LINKAGG_MODULE, SYS_LINKAGG_FAILOVER_PORTS_MAX * sizeof(uint32));
    if (NULL == failover.backup_ports)
    {
        ret = CTC_E_NO_MEMORY;
        goto OUT;
    }
    sal_memset(failover.backup_ports, 0, SYS_LINKAGG_LSH_PORTS_MAX * sizeof(uint32));

    for(loop1 = 0; loop1 < p_group->port_cnt; loop1++)
    {
        for (loop2 = 0; loop2 < p_group->port_cnt && failover.count < SYS_LINKAGG_LSH_PORTS_MAX; loop2++)
        {
            if(p_group->port_list[loop2]->gport == p_group->port_list[loop1]->gport)
            {
                continue;
            }

            failover.backup_ports[failover.count++] = p_group->port_list[loop2]->gport;
        }

        CTC_ERROR_GOTO(_sys_usw_linkagg_set_failover(lchip, p_group, p_group->port_list[loop1]->gport, &failover), ret, OUT);

        failover.count = 0;
        sal_memset(failover.backup_ports, 0, SYS_LINKAGG_LSH_PORTS_MAX * sizeof(uint32));
    }

    if(!is_add)
    {
        failover.count = 0;
        sal_memset(failover.backup_ports, 0, SYS_LINKAGG_LSH_PORTS_MAX * sizeof(uint32));
        CTC_ERROR_GOTO(_sys_usw_linkagg_set_failover(lchip, p_group, gport, &failover), ret, OUT);
    }

OUT:
    if(failover.backup_ports)
    {
       mem_free(failover.backup_ports);
    }
    return ret;
}
#endif

int32
_sys_usw_linkagg_remove_port(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 force_local, uint8 nonuc_block_en);

STATIC int32
_sys_usw_linkagg_add_port_hw(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 replace)
{
    uint8  gchip = 0;
    uint16 lport = 0;
    uint32 agg_gport = 0;
    int32 ret = CTC_E_NONE;
    sys_linkagg_mem_t linkagg_mem;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&linkagg_mem, 0, sizeof(linkagg_mem));
    gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(gport);

    linkagg_mem.tid = p_group->tid;
    linkagg_mem.gport = gport;
    linkagg_mem.linkagg_mode = p_group->mode;
    linkagg_mem.mem_valid_num = p_group->real_member_num + 1;

    switch (linkagg_mem.linkagg_mode)
    {
        case CTC_LINKAGG_MODE_STATIC:
        case CTC_LINKAGG_MODE_STATIC_FAILOVER:
        case CTC_LINKAGG_MODE_RR:
        {
            if(CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER))
            {
                uint16 tmp_index = p_group->real_member_num;
                DsLinkAggregateMember_m  hw_member;
                uint32 cmdr = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
                uint32 cmdw = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
                uint32 hw_gport;

                for(; tmp_index > 0; tmp_index--)
                {
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tmp_index+p_group->member_base-1, cmdr, &hw_member));
                    hw_gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(GetDsLinkAggregateMember(V, destChipId_f, &hw_member), \
                                                            GetDsLinkAggregateMember(V, destId_f, &hw_member));
                    if(SYS_LINKAGG_MAP_GPORT_TO_GCHIP_LPORT(gport) >= SYS_LINKAGG_MAP_GPORT_TO_GCHIP_LPORT(hw_gport))
                    {
                        break;
                    }
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tmp_index+p_group->member_base, cmdw, &hw_member));
                }
                linkagg_mem.port_index = tmp_index;
            }
            else
            {
                /*get the first unused pos*/
                linkagg_mem.port_index = p_group->real_member_num;
            }
            /*
             * member num 1~24:   member num in linkagg group:1~24
             * member num 25~32:  member num in linkagg group:25
             * member num 33~64:  member num in linkagg group:26
             * member num 65~128: member num in linkagg group:27
             */

            if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_1)
            {
                linkagg_mem.port_cnt = linkagg_mem.mem_valid_num;
                linkagg_mem.need_pad = 0;
            }
            else if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_2)
            {
                linkagg_mem.port_cnt = 25;
                if (linkagg_mem.mem_valid_num == 25)
                {
                    linkagg_mem.need_pad = 1;
                }
                else
                {
                    linkagg_mem.need_pad = 0;
                }
            }
            else if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_3)
            {
                linkagg_mem.port_cnt = 26;
                if (linkagg_mem.mem_valid_num == 33)
                {
                    linkagg_mem.need_pad = 1;
                }
                else
                {
                    linkagg_mem.need_pad = 0;
                }
            }
            else if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_4)
            {
                linkagg_mem.port_cnt = 27;
                if (linkagg_mem.mem_valid_num == 65)
                {
                    linkagg_mem.need_pad = 1;
                }
                else
                {
                    linkagg_mem.need_pad = 0;
                }
            }
            if (DRV_FROM_TM(lchip))
            {
                linkagg_mem.port_cnt = linkagg_mem.mem_valid_num;
                linkagg_mem.need_pad = 0;
            }
            break;
        }
        case CTC_LINKAGG_MODE_DLB:
        {
            linkagg_mem.port_cnt = linkagg_mem.mem_valid_num;
            linkagg_mem.port_index = p_group->real_member_num;
            break;
        }
        default:
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "linkagg group mode error!\n");
            ret = CTC_E_INVALID_PARAM;
            goto out;
        }
    }

    /*write asic table*/
    ret = _sys_usw_linkagg_update_table(lchip, p_group, &linkagg_mem, TRUE, replace);
    if (ret < 0)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg update asic table fail!\n");
        goto out;
    }

    /*for the first member in dlb mode ,need flush active */
    if (linkagg_mem.linkagg_mode == CTC_LINKAGG_MODE_DLB && linkagg_mem.mem_valid_num == 1)
    {
        ret = _sys_usw_linkagg_clear_flow_active(lchip, p_group->tid, 0, 0, 0);
        if (CTC_E_NONE != ret)
        {
            goto out;
        }
    }

    p_group->real_member_num++;

    if (!p_usw_linkagg_master[lchip]->bind_gport_disable)
    {
        lport = CTC_MAP_GPORT_TO_LPORT(gport);
        if (TRUE == sys_usw_chip_is_local(lchip, gchip) && (((p_group->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)) 
            && !CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))      /*old tid less MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)*/
            || ((CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))     /*nonuc detach TM: tid over group num*/
            && ((DRV_IS_TSINGMA(lchip) && (p_group->tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)))
            || DRV_FROM_TMM(lchip)))) && !p_group->is_lag)
        {
            agg_gport = CTC_MAP_TID_TO_GPORT(p_group->tid);
            sys_usw_port_api_set_global_port(lchip, lport, agg_gport, FALSE);
        }
    }

out:
    return ret;
}

int32
_sys_usw_linkagg_add_port(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 force_local, uint8 nonuc_block_en,uint8 replace)
{
    int32 ret = 0;
    uint16  index;
    uint8  gchip = 0;
    sys_linkagg_t* p_group_local_first;
    uint32  field_val = 0;
    uint32 cmd = 0;
    uint32 mux_type = 0;
    uint32 channel_id = 0;
    uint8 is_local_chip  = 0;
    uint8 add_uc_hw = 1;
    uint8 before_tm = DRV_IS_DUET2(lchip)|| DRV_IS_TSINGMA(lchip);
    uint16 loop = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    /*Sanity check*/
    SYS_GLOBAL_PORT_CHECK(gport);
    if(CTC_IS_CPU_PORT(gport) || CTC_IS_LINKAGG_PORT(gport))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[agg]Invalid gport!\n");
        return CTC_E_INVALID_PARAM;
    }

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "linkAggId: 0x%x,mem_port: 0x%x\n", p_group->tid, gport);

    gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(gport);
    SYS_GLOBAL_CHIPID_CHECK(gchip);

    if(before_tm && _sys_usw_linkagg_check_link_stats(lchip))
    {
        return CTC_E_HW_BUSY;
    }

   is_local_chip = sys_usw_chip_is_local(lchip, gchip) || force_local;
   if(is_local_chip)
   {
        dmps_port_info.gport = gport;
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
   }

   if (DRV_FROM_AT(lchip) && p_usw_linkagg_master[lchip]->xfabric_en)
   {
        uint32 value = 0;

        if (CTC_LINKAGG_MODE_STATIC != p_group->mode && CTC_LINKAGG_MODE_STATIC_FAILOVER != p_group->mode)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "xfabric mode only support static/failover!\n");
            ret = CTC_E_INVALID_CONFIG;
            goto out;
        }

        if (p_group->flag && CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER != p_group->flag)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "xfabric mode only support ascend order!\n");
            ret = CTC_E_INVALID_CONFIG;
            goto out;
        }

        if (!is_local_chip)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "xfabric mode do not support remote member!\n");
            ret = CTC_E_INVALID_CONFIG;
            goto out;
        }
        /*
        CTC_ERROR_RETURN(sys_usw_port_api_get_property(lchip, gport, CTC_PORT_PROP_XFABRIC_TYPE, &value));
        */
        if ((p_group->xfabric_type) && (p_group->xfabric_type != value))
        {
           ret = CTC_E_INVALID_CONFIG;
           goto out;
        }
        p_group->xfabric_type = value;
   }

   if ((CTC_LINKAGG_MODE_DLB == p_group->mode || CTC_LINKAGG_MODE_STATIC_FAILOVER == p_group->mode )
       &&   (!is_local_chip || !SYS_IS_NETWORK_CHANNEL(channel_id)))
   {
       SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid localphy port \n");
       ret =  CTC_E_INVALID_PORT;
       goto out;
   }

   if (CTC_LINKAGG_MODE_DLB == p_group->mode || CTC_LINKAGG_MODE_STATIC_FAILOVER == p_group->mode)
   {
       cmd = DRV_IOR(IpePhyPortMuxCtl_t, IpePhyPortMuxCtl_muxType_f);
       CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, channel_id, cmd, &mux_type), ret, out);
       if (mux_type > 0)
       {
           SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "DLB group or Static Failover group do not support mux port!\n");
           ret =  CTC_E_INVALID_PARAM;
           goto out;
       }
   }

    /*for static fail over, real member num may be changed, must reriver*/
    if(p_group->mode == CTC_LINKAGG_MODE_STATIC_FAILOVER && before_tm)
    {
        uint32 cmd_r = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggMemNum_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd_r, &field_val), ret, out);
        p_group->real_member_num = field_val;
    }
    /*check if the port is member of linkagg*/
    if (!replace && _sys_usw_linkagg_port_is_member(lchip, p_group, gport, &index, NULL))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The port is exist in linkagg group, add member port fail!\n");
        ret = CTC_E_EXIST;
        goto out;
    }

    if (p_group->real_member_num >= p_group->max_member_num || (DRV_FROM_TMM(lchip) && p_group->port_cnt >= p_group->max_member_num))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member of linkagg group reach Max, add member port fail!\n");
        ret = CTC_E_INVALID_PARAM;
        goto out;
    }

    switch (p_group->mode)
    {
        case CTC_LINKAGG_MODE_STATIC:
        {
            break;
        }
        case CTC_LINKAGG_MODE_STATIC_FAILOVER:
        {
            if (p_group->real_member_num >= SYS_LINKAGG_MEM_NUM_1 && before_tm)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member of linkagg group reach Max, add member port fail!\n");
                ret = CTC_E_INVALID_PARAM;
                goto out;
            }
            break;
        }
        case CTC_LINKAGG_MODE_RR:
        {
            if (p_group->real_member_num >= MCHIP_CAP(SYS_CAP_LINKAGG_RR_MAX_MEM_NUM))
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member of linkagg group reach Max, add member port fail!\n");
                ret = CTC_E_INVALID_PARAM;
                goto out;
            }
            break;
        }
        case CTC_LINKAGG_MODE_DLB:
        {
            if (p_group->real_member_num >= MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM))
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member of linkagg group reach Max, add member port fail!\n");
                ret = CTC_E_INVALID_PARAM;
                goto out;
            }
            break;
        }
        default:
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "linkagg group mode error!\n");
            ret = CTC_E_INVALID_PARAM;
            goto out;
        }
    }

     if (DRV_FROM_TMM(lchip) && (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) && (!CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)))
     {
        if(p_group->local_port_cnt == 0 && is_local_chip)
        {
           for (loop = 0; loop < p_group->port_cnt; loop++)
           {
               CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port_hw(lchip, p_group, p_group->port_list[loop]->gport, replace), ret, error_proc);
           }
        }
        add_uc_hw =  (is_local_chip || (p_group->local_port_cnt == 0)) ? 1 : 0;
     }


     if(add_uc_hw)
     {
          CTC_ERROR_GOTO(_sys_usw_linkagg_add_port_hw(lchip, p_group, gport, replace), ret, out);
     }

     nonuc_block_en = (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))?0:nonuc_block_en;
     /*add to db*/
     CTC_ERROR_GOTO(_sys_usw_linkagg_add_port_to_db( lchip, p_group,  gport, nonuc_block_en, is_local_chip), ret, out);

     if (MCHIP_LAG(lchip)->add_nonuc_ports && !replace && (!CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)))
     {
         CTC_ERROR_GOTO(MCHIP_LAG(lchip)->add_nonuc_ports( lchip, p_group, gport, nonuc_block_en), ret, error_proc);
     }

    /*Only D2 & TM do local member first need depend on original group flag*/
    if (p_group->cfg_lmpf && before_tm && is_local_chip && !replace)
    {
        if((p_group->mode != CTC_LINKAGG_MODE_STATIC) && (p_group->mode != CTC_LINKAGG_MODE_STATIC_FAILOVER))
        {
            ret = CTC_E_NOT_SUPPORT;
            goto out;
        }

        p_group_local_first = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, (p_group->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)));
        if(!p_group_local_first)
        {
            ret = CTC_E_NOT_EXIST;
            goto out;
        }

        CTC_ERROR_GOTO(_sys_usw_linkagg_add_port_hw(lchip, p_group_local_first, gport, 0), ret, error_proc);
        CTC_ERROR_GOTO(_sys_usw_linkagg_add_port_to_db( lchip, p_group_local_first,  gport, add_uc_hw, is_local_chip), ret, error_proc);
    }

     /*TMM update backup ports for all member ports*/
     if(p_group->lsh_mode && MCHIP_LAG(lchip)->set_lsh)
     {
        ctc_linkagg_lsh_t port_array;
        port_array.lsh_mode = p_group->lsh_mode;

        for (loop = 0; loop < p_group->port_cnt; loop++)
        {
            CTC_ERROR_GOTO(MCHIP_LAG(lchip)->set_lsh(lchip, p_group, p_group->port_list[loop]->gport, &port_array), ret, error_proc);
        }
     }

out:
    return ret;
error_proc:
    _sys_usw_linkagg_remove_port(lchip, p_group, gport, is_local_chip, nonuc_block_en);
    return ret;
}



/**
 @brief The function is to remove the port from linkagg
*/
int32
_sys_usw_linkagg_remove_port_hw(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 replace)
{
    int32   ret = CTC_E_NONE;
    uint16  index = 0;
    sys_linkagg_mem_t linkagg_mem;
    uint16  hw_index = 0;


    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&linkagg_mem, 0, sizeof(linkagg_mem));

    /*check if port is a member of linkagg*/
    if (FALSE == _sys_usw_linkagg_port_is_member(lchip, p_group, gport, &index, &hw_index) || (index == CTC_MAX_UINT16_VALUE))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The port is not exist in linkagg group, remove fail!\n");
        return CTC_E_NOT_EXIST;
    }


    linkagg_mem.tid = p_group->tid;
    linkagg_mem.gport = gport;
    linkagg_mem.linkagg_mode = p_group->mode;
    linkagg_mem.mem_valid_num = p_group->real_member_num - 1;
    linkagg_mem.port_index = hw_index;

    switch (linkagg_mem.linkagg_mode)
    {
        case CTC_LINKAGG_MODE_STATIC:
        case CTC_LINKAGG_MODE_STATIC_FAILOVER:
        case CTC_LINKAGG_MODE_RR:
        {
            if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_1 || (!DRV_IS_DUET2(lchip)&& !DRV_IS_TSINGMA(lchip)))
            {
                linkagg_mem.port_cnt = linkagg_mem.mem_valid_num;
            }
            else if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_2)
            {
                linkagg_mem.port_cnt = 25;
            }
            else if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_3)
            {
                linkagg_mem.port_cnt = 26;
            }
            else if (linkagg_mem.mem_valid_num <= SYS_LINKAGG_MEM_NUM_4)
            {
                linkagg_mem.port_cnt = 27;
            }
            else
            {
                /* keep port_cnt not change */
            }

            if (linkagg_mem.port_cnt > 24)
            {
                linkagg_mem.need_pad = 1;
            }
            else
            {
                linkagg_mem.need_pad = 0;
            }
            if (DRV_FROM_TM(lchip))
            {
                linkagg_mem.need_pad = 0;
                linkagg_mem.port_cnt = linkagg_mem.mem_valid_num;
            }
            break;
        }
        case CTC_LINKAGG_MODE_DLB:
        {
            linkagg_mem.port_cnt = linkagg_mem.mem_valid_num;
            break;
        }
        default:
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "linkagg group mode error!\n");
            ret = CTC_E_INVALID_PARAM;
            goto OUT;
        }
    }

    /*write asic table*/
    ret = _sys_usw_linkagg_update_table(lchip, p_group, &linkagg_mem, FALSE, replace);
    if (ret < 0)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg update asic table fail!\n");
        goto OUT;
    }

    p_group->real_member_num--;

OUT:
    return ret;
}

/**
 @brief The function is to add a port to linkagg, do not support wrr
*/
int32
sys_usw_linkagg_add_port(uint8 lchip, uint16 tid, uint32 gport)
{
    int32 ret = 0;
    uint8  member_cnt = 0;
    uint32 member_list[SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX] = {0};
    sys_linkagg_t* p_group = NULL;
    uint8 mirror_ref_cnt = 0;
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);

    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        LINKAGG_UNLOCK;
        return CTC_E_NOT_EXIST;
    }
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_add_port(lchip, p_group, gport, 0, 0,0),p_usw_linkagg_master[lchip]->p_linkagg_mutex);

    if(MCHIP_LAG(lchip)->update_mirror_dest)
    {
        ret = MCHIP_LAG(lchip)->update_mirror_dest(lchip, tid, 1);
        LINKAGG_UNLOCK;
        return ret;
    }

    if (p_group && p_group->mirror_ref_cnt)
    {
       mirror_ref_cnt = p_group->mirror_ref_cnt;
       member_cnt = SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX;
       ret = _sys_usw_linkagg_get_ports2(lchip, p_group, member_list, &member_cnt);
    }
    LINKAGG_UNLOCK;
    if (ret == CTC_E_NONE && mirror_ref_cnt)
    {
        SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, member_list, member_cnt, 1);
    }

    return ret;
}

int32
_sys_usw_linkagg_remove_port(uint8 lchip, sys_linkagg_t* p_group, uint32 gport, uint8 force_local, uint8 nonuc_block_en)
{
    int32 ret = CTC_E_NONE;
    uint8 is_local_chip = 0;
    sys_linkagg_t* p_group_local_first;
    ctc_linkagg_lsh_t port_array;
    uint8 add_uc_hw = 1;
    uint8 before_tm = DRV_IS_DUET2(lchip)|| DRV_IS_TSINGMA(lchip);
    uint16  index = 0;
    uint16  lport = 0;
    uint16  loop = 0;

    SYS_GLOBAL_PORT_CHECK(gport);
    if (CTC_IS_CPU_PORT(gport) || CTC_IS_LINKAGG_PORT(gport))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[linkagg]Invalid gport!\n");
        return CTC_E_INVALID_PARAM;
    }

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "linkAggId: 0x%x,mem_port: 0x%x\n", p_group->tid, gport);

    if (before_tm && _sys_usw_linkagg_check_link_stats(lchip))
    {
        return CTC_E_HW_BUSY;
    }
 
    /*clean backup ports for the port which will be remove*/
    if (MCHIP_LAG(lchip)->set_lsh)
    {
        sal_memset(&port_array, 0, sizeof(port_array));
        CTC_ERROR_GOTO(MCHIP_LAG(lchip)->set_lsh(lchip, p_group, gport, &port_array), ret, OUT);
    }

    /*for static fail over, real member num may be changed, must reriver*/
    if (p_group->mode == CTC_LINKAGG_MODE_STATIC_FAILOVER)
    {
        p_group->real_member_num = _sys_usw_dlb_get_real_member_num(lchip, p_group->tid);
    }

    if (0 == p_group->real_member_num)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member num of linkagg is zero, remove fail!\n");
        ret = CTC_E_NOT_EXIST;
        goto OUT;
    }

    if (FALSE == _sys_usw_linkagg_port_is_member(lchip, p_group, gport, &index, NULL))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The port is not exist in linkagg group, remove fail!\n");
        ret = CTC_E_NOT_EXIST;
        goto OUT;
    }
    is_local_chip = p_group->port_list[index]->is_local;
    if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
    {
        add_uc_hw = (before_tm || is_local_chip || (p_group->local_port_cnt == 0)) ? 1 : 0;
    }



    if (add_uc_hw)
    {
        CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port_hw(lchip, p_group, gport, 0), ret, OUT);
    }

    CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port_to_db( lchip, p_group,  gport), ret, OUT);
    if (MCHIP_LAG(lchip)->remove_nonuc_ports && !CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
    {
        CTC_ERROR_GOTO(MCHIP_LAG(lchip)->remove_nonuc_ports( lchip, p_group, gport, nonuc_block_en), ret, OUT);
    }

    /* the deleted member is  last force member(local and force member) and should add  all remote port to uc linkagg*/
    if (!before_tm && (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) && (p_group->local_port_cnt==0) && is_local_chip)
    {
        for (loop = 0; loop < p_group->port_cnt; loop++)
        {
            CTC_ERROR_GOTO(_sys_usw_linkagg_add_port_hw(lchip, p_group, p_group->port_list[loop]->gport, 0), ret, OUT);
        }
       
    }

    /*Only D2 & TM do local member first need depend on original group flag*/
    if (p_group->cfg_lmpf && before_tm && is_local_chip)
    {
        if ((p_group->mode != CTC_LINKAGG_MODE_STATIC) && (p_group->mode != CTC_LINKAGG_MODE_STATIC_FAILOVER))
        {
            ret = CTC_E_NOT_SUPPORT;
            goto OUT;
        }
        p_group_local_first = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, p_group->tid + MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
        if (!p_group_local_first)
        {
            ret = CTC_E_NOT_EXIST;
            goto OUT;
        }
        CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port_hw(lchip, p_group_local_first, gport, 0), ret, OUT);
        CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port_to_db( lchip, p_group_local_first,  gport), ret, OUT);
    }

    /*set local port's global_port*/
    if (!p_usw_linkagg_master[lchip]->bind_gport_disable)
    {
        if (is_local_chip && (((p_group->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)) 
            && !CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
            || ((CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)) 
            && (p_group->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)))))
        {
            /* check whether is the last one */
            if (FALSE == _sys_usw_linkagg_port_is_member(lchip, p_group, gport, &index, NULL))
            {
                lport = CTC_MAP_GPORT_TO_LPORT(gport);
                sys_usw_port_api_set_global_port(lchip, lport, gport, FALSE);
            }
        }
    }

     /*TMM update backup ports for all member ports*/
     if(p_group->lsh_mode && MCHIP_LAG(lchip)->set_lsh)
     {
        sal_memset(&port_array, 0, sizeof(port_array));
        port_array.lsh_mode = p_group->lsh_mode;

        for (loop = 0; loop < p_group->port_cnt; loop++)
        {
            CTC_ERROR_GOTO(MCHIP_LAG(lchip)->set_lsh(lchip, p_group, p_group->port_list[loop]->gport, &port_array), ret, OUT);
        }
     }
OUT:
    return ret;
}

int32
sys_usw_linkagg_remove_port(uint8 lchip, uint16 tid, uint32 gport)
{
    int32 ret = 0;
    uint8  member_cnt = 0;
    uint32 member_list[SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX] = {0};
    sys_linkagg_t* p_group = NULL;
    uint8 mirror_ref_cnt = 0;
    SYS_LINKAGG_INIT_CHECK();
    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        LINKAGG_UNLOCK;
        return CTC_E_NOT_EXIST;
    }
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_remove_port(lchip, p_group,  gport, 0, 0),p_usw_linkagg_master[lchip]->p_linkagg_mutex);

    if(MCHIP_LAG(lchip)->update_mirror_dest)
    {
        ret = MCHIP_LAG(lchip)->update_mirror_dest(lchip, tid, 1);
        LINKAGG_UNLOCK;
        return ret;
    }

    if (p_group && p_group->mirror_ref_cnt)
    {
       mirror_ref_cnt = p_group->mirror_ref_cnt;
       member_cnt = SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX;
       ret = _sys_usw_linkagg_get_ports2(lchip, p_group, member_list, &member_cnt);
    }
    LINKAGG_UNLOCK;
    if (ret == CTC_E_NONE && mirror_ref_cnt)
    {
        SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, member_list, member_cnt, 1);
    }
    return ret;
}
int32
sys_usw_linkagg_add_ports(uint8 lchip, uint16 tid, uint32 member_cnt, ctc_linkagg_port_t* p_ports)
{
    int32 ret = 0;
    uint32 loop = 0;
    uint32 loop1 = 0;
    uint8  member_cnt_new = 0;
    uint32 member_list[SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX] = {0};
    sys_linkagg_t* p_group = NULL;
    uint8 mirror_ref_cnt = 0;
    CTC_PTR_VALID_CHECK(p_ports);
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);
    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        LINKAGG_UNLOCK;
        return CTC_E_NOT_EXIST;
    }
    for (loop = 0; loop < member_cnt; loop ++)
    {
        CTC_ERROR_GOTO(_sys_usw_linkagg_add_port(lchip, p_group, p_ports[loop].gport, p_ports[loop].lmpf_en, p_ports[loop].nonuc_block_en,0), ret , OUT);
    }

    if(MCHIP_LAG(lchip)->update_mirror_dest)
    {
        CTC_ERROR_GOTO(MCHIP_LAG(lchip)->update_mirror_dest(lchip, tid, 1), ret, OUT);
        LINKAGG_UNLOCK;
        return CTC_E_NONE;
    }

    if (p_group && p_group->mirror_ref_cnt)
    {
       mirror_ref_cnt = p_group->mirror_ref_cnt;
       member_cnt_new = SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX;
       CTC_ERROR_GOTO(_sys_usw_linkagg_get_ports2(lchip, p_group, member_list, &member_cnt_new),ret,OUT);
    }
OUT:
    for (loop1 = 0; ret != CTC_E_NONE && loop1 < loop ; loop1 ++)
    {
        _sys_usw_linkagg_remove_port(lchip, p_group, p_ports[loop1].gport, p_ports[loop1].lmpf_en, p_ports[loop1].nonuc_block_en);
    }
    LINKAGG_UNLOCK;
    if (ret == CTC_E_NONE && mirror_ref_cnt)
    {
        SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, member_list, member_cnt_new, 1);
    }
    return ret;
}

int32
sys_usw_linkagg_remove_ports(uint8 lchip, uint16 tid, uint32 member_cnt, ctc_linkagg_port_t* p_ports)
{
    int32 ret = 0;
    uint32 loop = 0;
    uint8  member_cnt_new = 0;
    uint32 member_list[SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX] = {0};
    sys_linkagg_t* p_group = NULL;
    uint8 mirror_ref_cnt = 0;
    CTC_PTR_VALID_CHECK(p_ports);
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);
    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        LINKAGG_UNLOCK;
        return CTC_E_NOT_EXIST;
    }
    for (loop = 0; loop < member_cnt; loop ++)
    {
        CTC_ERROR_GOTO(_sys_usw_linkagg_remove_port(lchip, p_group, p_ports[loop].gport, p_ports[loop].lmpf_en, p_ports[loop].nonuc_block_en), ret , OUT);
    }

    if(MCHIP_LAG(lchip)->update_mirror_dest)
    {
        ret = MCHIP_LAG(lchip)->update_mirror_dest(lchip, tid, 1);
        LINKAGG_UNLOCK;
        return ret;
    }

    if (p_group && p_group->mirror_ref_cnt)
    {
       mirror_ref_cnt = p_group->mirror_ref_cnt;
       member_cnt_new = SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX;
       CTC_ERROR_GOTO(_sys_usw_linkagg_get_ports2(lchip, p_group, member_list, &member_cnt_new),ret,OUT);
    }
OUT:
    LINKAGG_UNLOCK;
    if (ret == CTC_E_NONE && mirror_ref_cnt)
    {
        SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, member_list, member_cnt_new, 1);
    }
    return ret;
}


/**
 @brief The function is to get the a local member port of linkagg
*/
int32
sys_usw_linkagg_get_1st_local_port(uint8 lchip, uint16 tid, uint32* p_gport, uint16* local_cnt)
{
    uint16 mem_idx = 0;
    sys_linkagg_t* p_group = NULL;
    /*Sanity check*/
    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_gport);
    CTC_PTR_VALID_CHECK(local_cnt);
    SYS_TID_VALID_CHECK(tid);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LINKAGG_LOCK;
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Entry is not exist \n");
        LINKAGG_UNLOCK;
        return CTC_E_NOT_EXIST;
    }

    *local_cnt = 0;
    for (mem_idx = 0; mem_idx < p_group->port_cnt; mem_idx++)
    {
        if (p_group->port_list[mem_idx] && p_group->port_list[mem_idx]->is_local && sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(p_group->port_list[mem_idx]->gport)))
        {
            *p_gport = p_group->port_list[mem_idx]->gport;
            (*local_cnt)++;
        }
    }
    LINKAGG_UNLOCK;
    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_get_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16* cnt)
{
    uint16 mem_idx = 0;
    sys_linkagg_t* p_group = NULL;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Entry is not exist \n");
        return CTC_E_NOT_EXIST;
    }

    for (mem_idx = 0; mem_idx < p_group->port_cnt; mem_idx++)
    {
        if (p_group->port_list[mem_idx])
        {
            p_gports[(*cnt)++] = p_group->port_list[mem_idx]->gport;
        }
    }
    return CTC_E_NONE;
}

/**
 @brief The function is to show member ports of linkagg.
*/
int32
sys_usw_linkagg_get_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16* cnt)
{
    int32 ret = 0;
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);
    CTC_PTR_VALID_CHECK(p_gports);
    CTC_PTR_VALID_CHECK(cnt);
    LINKAGG_LOCK;
    CTC_ERROR_GOTO(_sys_usw_linkagg_get_ports(lchip, tid, p_gports, cnt),ret,OUT);
OUT:
    LINKAGG_UNLOCK;
    return ret;
}

int32
_sys_usw_linkagg_get_ports2(uint8 lchip, sys_linkagg_t* p_group, uint32* member_list, uint8* p_member_cnt)
{
    uint8  gchip_id = 0;
    uint8  is_new = 0;
    uint8  local_only = 0;
    uint16 mem_idx = 0;
    uint16 loop = 0;
    uint8 array_num = 0;

    if (0 == (*p_member_cnt))
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));

    array_num = *p_member_cnt;
    *p_member_cnt = 0;

    if (0 == p_group->port_cnt)
    {
        return CTC_E_NONE;
    }

    local_only = ((p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) && p_group->local_port_cnt)? 1 : 0;

    for (mem_idx = 0; mem_idx < p_group->port_cnt && (*p_member_cnt) < array_num; mem_idx++)
    {
        is_new = 1;
        if (!p_group->port_list[mem_idx])
        {
            continue;
        }

        for (loop = 0; loop < (*p_member_cnt); loop++)
        {
            if (p_group->port_list[mem_idx]->gport == member_list[loop])
            {
                is_new = 0;
                break;
            }
        }
        if (is_new && (!local_only || p_group->port_list[mem_idx]->is_local))
        {
            member_list[(*p_member_cnt)++] = p_group->port_list[mem_idx]->gport;
        }
    }

    return CTC_E_NONE;
}

/*get member list with no repeat*/
int32
sys_usw_linkagg_get_ports2(uint8 lchip, uint16 tid, uint32* member_list, uint8* p_member_cnt)
{
    sys_linkagg_t* p_group = NULL;
    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);
    CTC_PTR_VALID_CHECK(member_list);
    CTC_PTR_VALID_CHECK(p_member_cnt);

    LINKAGG_LOCK;
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        LINKAGG_UNLOCK;
        return CTC_E_NOT_EXIST;
    }
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_get_ports2(lchip, p_group, member_list, p_member_cnt), p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    LINKAGG_UNLOCK;

    return CTC_E_NONE;
}

/**
 @brief The function is to show member ports of linkagg.
*/
int32
sys_usw_linkagg_show_all_member(uint8 lchip, uint16 tid)
{
    uint16 idx = 0;
    uint16 mem_num = 0;
    uint16 mem_max_num = 0;
    int32  ret = 0;
    sys_linkagg_t* p_group = NULL;
    uint32 cmd        = 0;
    char* mode[4] = {"static", "static-failover", "round-robin", "dynamic"};
    char flag_str[64];
    int32 usedlen;
    uint8  valid = 0;
    uint32 value[32] = {0};

    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    LINKAGG_LOCK;

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Entry is not exist \n");
        ret = CTC_E_NOT_EXIST;
        goto OUT;
    }

    /*for static fail over, real member num may be changed, must reriver*/
    if (p_group->mode == CTC_LINKAGG_MODE_STATIC_FAILOVER)
    {
        p_group->real_member_num = _sys_usw_dlb_get_real_member_num(lchip, p_group->tid);
    }

    if (DRV_FROM_TMM(lchip) && (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST))
    {
        mem_num = p_group->port_cnt;
    }
    else
    {
        mem_num = p_group->real_member_num;
    }
    mem_max_num = p_group->max_member_num;

    flag_str[0] = '\0';
    if (0 == (p_group->flag & (CTC_LINKAGG_GROUP_FLAG_RANDOM_RR | CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER | CTC_LINKAGG_GROUP_FLAG_SPM_EN | CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)) 
        && !p_group->cfg_lmpf)
    {
        sal_sprintf(flag_str, "%s", "- ");
    }
    else
    {
        usedlen = 0;

        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_RANDOM_RR)
        {
            usedlen += sal_sprintf(flag_str + usedlen, "random ");
        }

        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
        {
            usedlen += sal_sprintf(flag_str + usedlen, "lmpf ");
        }

        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_MEM_ASCEND_ORDER)
        {
            usedlen += sal_sprintf(flag_str + usedlen, "mem-asend-order ");
        }

        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN)
        {
            usedlen += sal_sprintf(flag_str + usedlen, "session-preservation ");
        }

        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)
        {
            usedlen += sal_sprintf(flag_str + usedlen, "nonuc-detach ");
        }
    }

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s: %u\n", "tid", tid);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s: %s\n", "mode", mode[p_group->mode]);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s: %s\n", "flag", flag_str);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s: %u\n", "count", mem_num);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s: %u\n", "membase",  p_group->member_base);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-11s%-15s%-8s         %-8s\n", "No.", "Member-Port", "LMPF-En", "Lsh-en");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------\n");

    if (mem_max_num == 0)
    {
        goto OUT;
    }

    for (idx = 0; idx < p_group->port_cnt; idx++)
    {
        if (DRV_FROM_TMM(lchip) && sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(p_group->port_list[idx]->gport)))
        {
            cmd = DRV_IOR(PortLagLinkSelfHealingEn_t, PortLagLinkSelfHealingEn_enableBitmap_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &value), ret, OUT);
            valid = CTC_IS_BIT_SET(value[CTC_MAP_GPORT_TO_LPORT(p_group->port_list[idx]->gport) / 32], CTC_MAP_GPORT_TO_LPORT(p_group->port_list[idx]->gport) % 32);
        }
        else
        {
            valid = 0;
        }
        if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-11u0x%04X         %-8s         %-8u\n", idx + 1,p_group->port_list[idx]->gport,p_group->port_list[idx]->is_local?"Enable":"Disable",valid);
        }
        else
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-11u0x%04X         %-8s         %-8u\n", idx + 1,p_group->port_list[idx]->gport,"Disable",valid);
        }
    }
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------\n");

OUT:
    LINKAGG_UNLOCK;
    return ret;
}

/**
 @brief The function is to set member of linkagg hash key
*/
int32
sys_usw_linkagg_set_psc(uint8 lchip, ctc_linkagg_psc_t* p_psc)
{
    uint32 value = 0;
    ctc_parser_linkagg_hash_ctl_t hash_ctl;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_LINKAGG_INIT_CHECK();

    sal_memset(&hash_ctl, 0, sizeof(ctc_parser_linkagg_hash_ctl_t));

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_INNER))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_INNER);
    }
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L2_ONLY))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_L2_ONLY);
    }
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L2))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_L2);

        value = CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_VLAN);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_STAG_VID : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_COS);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_STAG_COS : 0));
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_CTAG_COS : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag ,CTC_LINKAGG_PSC_L2_ETHERTYPE);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_ETHERTYPE : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_DOUBLE_VLAN);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_STAG_VID : 0));
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_CTAG_VID : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACSA);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_MACSA : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag,  CTC_LINKAGG_PSC_L2_MACDA);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_MACDA : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag,  CTC_LINKAGG_PSC_L2_PORT);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_PORT : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag,  CTC_LINKAGG_PSC_L2_DST_PORT);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_DST_PORT : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag,  CTC_LINKAGG_PSC_L2_SRC_CHIP_ID);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_SRC_CHIP_ID : 0));

        value = CTC_FLAG_ISSET(p_psc->l2_flag,  CTC_LINKAGG_PSC_L2_DST_CHIP_ID);
        CTC_SET_FLAG(hash_ctl.l2_flag, (value ? CTC_PARSER_L2_HASH_FLAGS_DST_CHIP_ID : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_IP))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_IP);

        value = CTC_FLAG_ISSET(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_PROTOCOL);
        CTC_SET_FLAG(hash_ctl.ip_flag, (value ? CTC_PARSER_IP_HASH_FLAGS_PROTOCOL : 0));

        value = CTC_FLAG_ISSET(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPSA);
        CTC_SET_FLAG(hash_ctl.ip_flag, (value ? CTC_PARSER_IP_HASH_FLAGS_IPSA : 0));

        value = CTC_FLAG_ISSET(p_psc->ip_flag ,CTC_LINKAGG_PSC_IP_IPDA);
        CTC_SET_FLAG(hash_ctl.ip_flag, (value ? CTC_PARSER_IP_HASH_FLAGS_IPDA : 0));

        value = CTC_FLAG_ISSET(p_psc->ip_flag ,CTC_LINKAGG_PSC_IP_DSCP);
        CTC_SET_FLAG(hash_ctl.ip_flag, (value ? CTC_PARSER_IP_HASH_FLAGS_DSCP : 0));

        value = CTC_FLAG_ISSET(p_psc->ip_flag ,CTC_LINKAGG_PSC_IPV6_FLOW_LABEL);
        CTC_SET_FLAG(hash_ctl.ip_flag, (value ? CTC_PARSER_IP_HASH_FLAGS_IPV6_FLOW_LABEL : 0));

        value = CTC_FLAG_ISSET(p_psc->ip_flag ,CTC_LINKAGG_PSC_IP_ECN);
        CTC_SET_FLAG(hash_ctl.ip_flag, (value ? CTC_PARSER_IP_HASH_FLAGS_ECN : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L4))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_L4);

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_SRC_PORT);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_SRC_PORT : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_DST_PORT);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_DST_PORT : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_GRE_KEY);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_GRE_KEY : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_TYPE);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_TYPE : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_USER_TYPE);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_USER_TYPE : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_VXLAN_L4_SRC_PORT);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_VXLAN_L4_SRC_PORT : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_TCP_FLAG);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_TCP_FLAG : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_TCP_ECN);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_TCP_ECN : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_NVGRE_VSID);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_NVGRE_VSID : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_NVGRE_FLOW_ID);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_NVGRE_FLOW_ID : 0));

        value = CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_VXLAN_VNI);
        CTC_SET_FLAG(hash_ctl.l4_flag, (value ? CTC_PARSER_L4_HASH_FLAGS_L4_VXLAN_VNI : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_PBB))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_PBB);

        value = CTC_FLAG_ISSET(p_psc->pbb_flag, CTC_LINKAGG_PSC_PBB_BMACDA);
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_CMAC_DA : 0));

        value = CTC_FLAG_ISSET(p_psc->pbb_flag, CTC_LINKAGG_PSC_PBB_BMACSA);
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_CMAC_SA : 0));

        value = CTC_FLAG_ISSET(p_psc->pbb_flag, CTC_LINKAGG_PSC_PBB_ISID);
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_ISID : 0));

        value = CTC_FLAG_ISSET(p_psc->pbb_flag, CTC_LINKAGG_PSC_PBB_BVLAN);
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_STAG_VID : 0));
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_CTAG_VID : 0));

        value = CTC_FLAG_ISSET(p_psc->pbb_flag, CTC_LINKAGG_PSC_PBB_BCOS);
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_STAG_COS : 0));
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_CTAG_COS : 0));

        value = CTC_FLAG_ISSET(p_psc->pbb_flag, CTC_LINKAGG_PSC_PBB_BCFI);
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_STAG_CFI : 0));
        CTC_SET_FLAG(hash_ctl.pbb_flag, (value ? CTC_PARSER_PBB_HASH_FLAGS_CTAG_CFI : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_MPLS))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_MPLS);

        value = CTC_FLAG_ISSET(p_psc->mpls_flag, CTC_LINKAGG_PSC_MPLS_PROTOCOL);
        CTC_SET_FLAG(hash_ctl.mpls_flag, (value ? CTC_PARSER_MPLS_HASH_FLAGS_PROTOCOL : 0));

        value = CTC_FLAG_ISSET(p_psc->mpls_flag, CTC_LINKAGG_PSC_MPLS_IPSA);
        CTC_SET_FLAG(hash_ctl.mpls_flag, (value ? CTC_PARSER_MPLS_HASH_FLAGS_IPSA : 0));

        value = CTC_FLAG_ISSET(p_psc->mpls_flag, CTC_LINKAGG_PSC_MPLS_IPDA);
        CTC_SET_FLAG(hash_ctl.mpls_flag, (value ? CTC_PARSER_MPLS_HASH_FLAGS_IPDA : 0));

        value = CTC_FLAG_ISSET(p_psc->mpls_flag, CTC_LINKAGG_PSC_MPLS_CANCEL_LABEL);
        CTC_SET_FLAG(hash_ctl.mpls_flag, (value ? CTC_PARSER_MPLS_HASH_FLAGS_CANCEL_LABEL : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_TRILL))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_TRILL);

        value = CTC_FLAG_ISSET(p_psc->trill_flag, CTC_LINKAGG_PSC_TRILL_INNER_VID);
        CTC_SET_FLAG(hash_ctl.trill_flag, (value ? CTC_PARSER_TRILL_HASH_FLAGS_INNER_VLAN_ID : 0));

        value = CTC_FLAG_ISSET(p_psc->trill_flag, CTC_LINKAGG_PSC_TRILL_INGRESS_NICKNAME);
        CTC_SET_FLAG(hash_ctl.trill_flag, (value ? CTC_PARSER_TRILL_HASH_FLAGS_INGRESS_NICKNAME : 0));

        value = CTC_FLAG_ISSET(p_psc->trill_flag, CTC_LINKAGG_PSC_TRILL_EGRESS_NICKNAME);
        CTC_SET_FLAG(hash_ctl.trill_flag, (value ? CTC_PARSER_TRILL_HASH_FLAGS_EGRESS_NICKNAME : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_FCOE))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_FCOE);

        value = CTC_FLAG_ISSET(p_psc->fcoe_flag, CTC_LINKAGG_PSC_FCOE_SID);
        CTC_SET_FLAG(hash_ctl.fcoe_flag, (value ? CTC_PARSER_FCOE_HASH_FLAGS_SID : 0));

        value = CTC_FLAG_ISSET(p_psc->fcoe_flag, CTC_LINKAGG_PSC_FCOE_DID);
        CTC_SET_FLAG(hash_ctl.fcoe_flag, (value ? CTC_PARSER_FCOE_HASH_FLAGS_DID : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_COMMON))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_COMMON);

        value = CTC_FLAG_ISSET(p_psc->common_flag, CTC_LINKAGG_PSC_COMMON_DEVICEINFO);
        CTC_SET_FLAG(hash_ctl.common_flag, (value ? CTC_PARSER_COMMON_HASH_FLAGS_DEVICEINFO : 0));
    }

    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_UDF))
    {
        CTC_SET_FLAG(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_UDF);
        hash_ctl.udf_bitmap = p_psc->udf_bitmap;
        hash_ctl.udf_id = p_psc->udf_id;
    }

    CTC_ERROR_RETURN(sys_usw_parser_set_linkagg_hash_field(lchip, &hash_ctl));

    return CTC_E_NONE;
}

/**
 @brief The function is to get member of linkagg hash key
*/
int32
sys_usw_linkagg_get_psc(uint8 lchip, ctc_linkagg_psc_t* p_psc)
{
    uint32 value1 = 0;
    uint32 value2 = 0;
    ctc_parser_linkagg_hash_ctl_t hash_ctl;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_LINKAGG_INIT_CHECK();

    sal_memset(&hash_ctl, 0, sizeof(ctc_parser_linkagg_hash_ctl_t));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L2);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_L2 : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_IP);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_IP : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L4);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_L4 : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_PBB);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_PBB : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_MPLS);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_MPLS : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_TRILL);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_TRILL : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_FCOE);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_FCOE : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_COMMON);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_COMMON : 0));

    value1 = CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_UDF);
    CTC_SET_FLAG(hash_ctl.hash_type_bitmap, (value1 ? CTC_PARSER_HASH_TYPE_FLAGS_UDF : 0));

    hash_ctl.udf_id = p_psc->udf_id;

    CTC_ERROR_RETURN(sys_usw_parser_get_linkagg_hash_field(lchip, &hash_ctl));

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_L2))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_STAG_VID);
        value2 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_CTAG_VID);

        if (value1 && value2)
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_DOUBLE_VLAN);
        }
        else if (value1 || value2)
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_VLAN);
        }

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_STAG_COS);
        value2 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_CTAG_COS);

        if (value1 || value2)
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_COS);
        }

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_ETHERTYPE);
        CTC_SET_FLAG(p_psc->l2_flag, (value1 ? CTC_LINKAGG_PSC_L2_ETHERTYPE : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_MACSA );
        CTC_SET_FLAG(p_psc->l2_flag, value1 ? CTC_LINKAGG_PSC_L2_MACSA : 0);

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_MACDA );
        CTC_SET_FLAG(p_psc->l2_flag, value1 ? CTC_LINKAGG_PSC_L2_MACDA : 0);

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_PORT);
        CTC_SET_FLAG(p_psc->l2_flag, value1 ? CTC_LINKAGG_PSC_L2_PORT: 0);

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_DST_PORT);
        CTC_SET_FLAG(p_psc->l2_flag, value1 ? CTC_LINKAGG_PSC_L2_DST_PORT: 0);

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_SRC_CHIP_ID);
        CTC_SET_FLAG(p_psc->l2_flag, value1 ? CTC_LINKAGG_PSC_L2_SRC_CHIP_ID: 0);

        value1 = CTC_FLAG_ISSET(hash_ctl.l2_flag, CTC_PARSER_L2_HASH_FLAGS_DST_CHIP_ID);
        CTC_SET_FLAG(p_psc->l2_flag, value1 ? CTC_LINKAGG_PSC_L2_DST_CHIP_ID: 0);
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_IP))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.ip_flag, CTC_PARSER_IP_HASH_FLAGS_PROTOCOL);
        CTC_SET_FLAG(p_psc->ip_flag, (value1 ? CTC_LINKAGG_PSC_IP_PROTOCOL : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.ip_flag, CTC_PARSER_IP_HASH_FLAGS_IPSA);
        CTC_SET_FLAG(p_psc->ip_flag, (value1 ? CTC_LINKAGG_PSC_IP_IPSA  : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.ip_flag, CTC_PARSER_IP_HASH_FLAGS_IPDA);
        CTC_SET_FLAG(p_psc->ip_flag, (value1 ? CTC_LINKAGG_PSC_IP_IPDA : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.ip_flag, CTC_PARSER_IP_HASH_FLAGS_DSCP);
        CTC_SET_FLAG(p_psc->ip_flag, (value1 ? CTC_LINKAGG_PSC_IP_DSCP  : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.ip_flag, CTC_PARSER_IP_HASH_FLAGS_IPV6_FLOW_LABEL);
        CTC_SET_FLAG(p_psc->ip_flag, (value1 ? CTC_LINKAGG_PSC_IPV6_FLOW_LABEL  : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.ip_flag, CTC_PARSER_IP_HASH_FLAGS_ECN);
        CTC_SET_FLAG(p_psc->ip_flag, (value1 ? CTC_LINKAGG_PSC_IP_ECN  : 0));
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_L4))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_SRC_PORT);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_SRC_PORT : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_DST_PORT);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_DST_PORT : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_GRE_KEY);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_GRE_KEY : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_TYPE);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_TYPE : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_USER_TYPE);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_USER_TYPE : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_VXLAN_L4_SRC_PORT);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_VXLAN_L4_SRC_PORT : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_TCP_FLAG);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_TCP_FLAG : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_TCP_ECN);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_TCP_ECN : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_NVGRE_VSID);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_NVGRE_VSID : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_NVGRE_FLOW_ID);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_NVGRE_FLOW_ID : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.l4_flag, CTC_PARSER_L4_HASH_FLAGS_L4_VXLAN_VNI);
        CTC_SET_FLAG(p_psc->l4_flag, (value1 ? CTC_LINKAGG_PSC_L4_VXLAN_VNI : 0));
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_PBB))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_CMAC_DA);
        CTC_SET_FLAG(p_psc->pbb_flag, (value1 ? CTC_LINKAGG_PSC_PBB_BMACDA : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_CMAC_SA);
        CTC_SET_FLAG(p_psc->pbb_flag, (value1 ? CTC_LINKAGG_PSC_PBB_BMACSA : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_ISID);
        CTC_SET_FLAG(p_psc->pbb_flag, (value1 ? CTC_LINKAGG_PSC_PBB_ISID : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_STAG_VID);
        value2 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_CTAG_VID);
        CTC_SET_FLAG(p_psc->pbb_flag, ((value1 && value2) ? CTC_LINKAGG_PSC_PBB_BVLAN : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_STAG_COS);
        value2 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_CTAG_COS);
        CTC_SET_FLAG(p_psc->pbb_flag, ((value1 && value2) ? CTC_LINKAGG_PSC_PBB_BCOS : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_STAG_CFI);
        value2 = CTC_FLAG_ISSET(hash_ctl.pbb_flag, CTC_PARSER_PBB_HASH_FLAGS_CTAG_CFI);
        CTC_SET_FLAG(p_psc->pbb_flag, ((value1 && value2) ? CTC_LINKAGG_PSC_PBB_BCFI : 0));
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_MPLS))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.mpls_flag, CTC_PARSER_MPLS_HASH_FLAGS_PROTOCOL);
        CTC_SET_FLAG(p_psc->mpls_flag, (value1 ? CTC_LINKAGG_PSC_MPLS_PROTOCOL : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.mpls_flag, CTC_PARSER_MPLS_HASH_FLAGS_IPSA);
        CTC_SET_FLAG(p_psc->mpls_flag, (value1 ? CTC_LINKAGG_PSC_MPLS_IPSA : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.mpls_flag, CTC_PARSER_MPLS_HASH_FLAGS_IPDA);
        CTC_SET_FLAG(p_psc->mpls_flag, (value1 ? CTC_LINKAGG_PSC_MPLS_IPDA : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.mpls_flag, CTC_PARSER_MPLS_HASH_FLAGS_CANCEL_LABEL);
        CTC_SET_FLAG(p_psc->mpls_flag, (value1 ? CTC_LINKAGG_PSC_MPLS_CANCEL_LABEL : 0));
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_TRILL))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.trill_flag, CTC_PARSER_TRILL_HASH_FLAGS_INNER_VLAN_ID);
        CTC_SET_FLAG(p_psc->trill_flag, (value1 ? CTC_LINKAGG_PSC_TRILL_INNER_VID : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.trill_flag, CTC_PARSER_TRILL_HASH_FLAGS_INGRESS_NICKNAME);
        CTC_SET_FLAG(p_psc->trill_flag, (value1 ? CTC_LINKAGG_PSC_TRILL_INGRESS_NICKNAME : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.trill_flag, CTC_PARSER_TRILL_HASH_FLAGS_EGRESS_NICKNAME);
        CTC_SET_FLAG(p_psc->trill_flag, (value1 ? CTC_LINKAGG_PSC_TRILL_EGRESS_NICKNAME : 0));
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_FCOE))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.fcoe_flag, CTC_PARSER_FCOE_HASH_FLAGS_SID);
        CTC_SET_FLAG(p_psc->fcoe_flag, (value1 ? CTC_LINKAGG_PSC_FCOE_SID : 0));

        value1 = CTC_FLAG_ISSET(hash_ctl.fcoe_flag, CTC_PARSER_FCOE_HASH_FLAGS_DID);
        CTC_SET_FLAG(p_psc->fcoe_flag, (value1 ? CTC_LINKAGG_PSC_FCOE_DID : 0));
    }

    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_COMMON))
    {
        value1 = CTC_FLAG_ISSET(hash_ctl.common_flag, CTC_PARSER_COMMON_HASH_FLAGS_DEVICEINFO);
        CTC_SET_FLAG(p_psc->common_flag, (value1 ? CTC_LINKAGG_PSC_COMMON_DEVICEINFO : 0));
    }
    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_UDF))
    {
        p_psc->udf_bitmap = hash_ctl.udf_bitmap;
    }
    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_INNER))
    {
        CTC_SET_FLAG(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_INNER);
    }
    if (CTC_FLAG_ISSET(hash_ctl.hash_type_bitmap, CTC_PARSER_HASH_TYPE_FLAGS_L2_ONLY))
    {
        CTC_SET_FLAG(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L2_ONLY);
    }
    return CTC_E_NONE;
}

/**
 @brief The function is to get member of linkagg, only useful in nor flex mode
*/
int32
sys_usw_linkagg_get_max_mem_num(uint8 lchip, uint16* max_num)
{
    uint16 mem_num = 0;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(max_num);

    switch (p_usw_linkagg_master[lchip]->linkagg_mode)
    {
        case CTC_LINKAGG_MODE_FLEX:
        {
            mem_num = 2048;
            break;
        }
        case CTC_LINKAGG_MODE_56:
        {
            mem_num = 32;
            break;
        }
        case CTC_LINKAGG_MODE_4:
        case CTC_LINKAGG_MODE_8:
        case CTC_LINKAGG_MODE_16:
        case CTC_LINKAGG_MODE_32:
        case CTC_LINKAGG_MODE_64:
        {
            mem_num = MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM) / MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM);
            if(mem_num > MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM))
            {
                mem_num = MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM);
            }
            break;
        }
        default:
        {
            break;
        }
    }

    *max_num = mem_num;

    return CTC_E_NONE;
}

int32
 _sys_usw_linkagg_update_dlb_flow(uint8 lchip, sys_linkagg_t* p_group, uint32* gport, uint16 mem_num)
{
    int32 ret = 0;
    uint32 cmd = 0;
    uint32 mem_base = 0;
    uint8 wait_cnt = 0;
    uint8 loop = 0;
    sys_usw_opf_t opf;
    DsLinkAggregateMember_m ds_linkagg_member;
    DsLinkAggregateGroup_m ds_linkagg_group;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    sal_memset(&opf, 0, sizeof(opf));
    if (DRV_FROM_TMM(lchip))
    {
        /*1. alloc static member*/
        opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;
        opf.pool_index = 0;
        opf.multiple = 1;
        ret = sys_usw_opf_alloc_offset(lchip, &opf, mem_num, &mem_base);
        if (ret == CTC_E_NO_RESOURCE)
        {
            _sys_usw_linkagg_fragment(lchip);
            ret = sys_usw_opf_alloc_offset(lchip, &opf, mem_num, &mem_base);
        }
    }

    /*2 alloc static member fail*/
    if(!DRV_FROM_TMM(lchip) || ret != CTC_E_NONE)
    {
        do
        {
            _sys_usw_linkagg_clear_flow_active(lchip, p_group->tid, 0, p_group->member_base, p_group->max_member_num);
            sal_task_sleep(10);
            wait_cnt++;
        }while (wait_cnt <= 10);
        return CTC_E_NONE;
    }

    /*3. alloc static member success*/
    /*3.1 prepare static member*/
    for (loop = 0; loop < mem_num; loop ++)
    {
        uint32 channel_id = 0;
        dmps_port_info.gport = gport[loop];
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &channel_id));
        cmd = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, mem_base + loop, cmd, &ds_linkagg_member);
        SetDsLinkAggregateMember(V, destId_f, &ds_linkagg_member, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport[loop]));
        SetDsLinkAggregateMember(V, destChipId_f, &ds_linkagg_member, SYS_MAP_CTC_GPORT_TO_GCHIP(gport[loop]));
        SetDsLinkAggregateMember(V, destChannelId_f, &ds_linkagg_member, SYS_USW_CHANNEL_ENCODE(channel_id));
        cmd = DRV_IOW(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, mem_base + loop, cmd, &ds_linkagg_member);
    }

    /*3.1 change to static mode*/
    cmd = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_group->tid, cmd, &ds_linkagg_group);
    SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, 0);
    SetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_linkagg_group, mem_base);
    cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_group->tid, cmd, &ds_linkagg_group);

    /*3.2 clear to dlb flow table*/
    _sys_usw_linkagg_clear_flow_active(lchip, p_group->tid, 0, p_group->member_base, p_group->max_member_num);

    /*3.3 change to dlb mode*/
    SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, 1);
    SetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_linkagg_group, p_group->member_base);
    cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_group->tid, cmd, &ds_linkagg_group);

    /*4. free static member*/
    sys_usw_opf_free_offset(lchip, &opf, mem_num, mem_base);
    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_replace_ports(uint8 lchip, uint16 tid, uint32* gport, uint16 mem_num, uint32 flag)
{
    int32 ret = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sys_linkagg_t* p_src_group = NULL;
    sys_linkagg_t  old_group;
     DsLinkAggregateGroup_m ds_linkagg_group;
    uint32 cmd = 0;
    uint32 mem_base;
    uint16 loop=0,loop2 = 0;
    sys_usw_opf_t opf;
    uint8 is_alloc_en =0;
    uint32 tmp = 0;
    uint8 before_tm = DRV_IS_DUET2(lchip)|| DRV_IS_TSINGMA(lchip);

    p_src_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_src_group || (DRV_IS_DUET2(lchip) && !(flag & SYS_LAG_REP_FIXED_MEM) && mem_num > 24)
        || ((p_src_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST) && before_tm) 
        || p_src_group->lsh_mode
        || ( p_src_group->mode != CTC_LINKAGG_MODE_STATIC && p_src_group->mode != CTC_LINKAGG_MODE_RR && p_src_group->mode != CTC_LINKAGG_MODE_DLB)
        || ( (flag & SYS_LAG_REP_FIXED_MEM) && mem_num > p_src_group->max_member_num) || (mem_num > MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM))
        || (p_src_group->mode == CTC_LINKAGG_MODE_DLB && mem_num > MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM)))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Entry is not exist \n");
        ret = CTC_E_NOT_SUPPORT;
        goto error_proc_0;
    }

    sal_memcpy(&old_group, p_src_group, sizeof(old_group));
    /*1.find the old member isn't linkagg member*/
     for (loop = 0; loop < old_group.port_cnt; loop++)
    {
        old_group.port_list[loop]->valid = 0;
        for (loop2 = 0; loop2 < mem_num; loop2++)
        {
            if (old_group.port_list[loop]->gport == gport[loop2])
            {
                 old_group.port_list[loop]->valid = 1;
            }
        }
    }
    /* 2. alloc, DLB don't need alloc */
    if(p_src_group->mode == CTC_LINKAGG_MODE_DLB)
    {
        uint32 port_type = 0;
        for (loop = 0; loop < mem_num; loop++)
        {
            dmps_port_info.gport = gport[loop];
            CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
            if ((SYS_DMPS_NETWORK_PORT != port_type) && (SYS_DMPS_CPUMAC_NETWORK_PORT != port_type) )
            {
                return CTC_E_INVALID_CONFIG;
            }
        }
    }
    else
    {
        sal_memset(&opf, 0, sizeof(opf));
        opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;
        opf.pool_index = 0;
        opf.multiple = 1;
        is_alloc_en = !(flag & SYS_LAG_REP_FIXED_MEM) && mem_num
                        && ( old_group.port_cnt !=0  ||  (mem_num > old_group.max_member_num ));
        if(is_alloc_en)
        {
            if(mem_num > (MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM)-sys_usw_opf_get_alloced_cnt(lchip, &opf)))
            {
                ret = CTC_E_NO_RESOURCE;
                goto error_proc_0;
            }
            ret = sys_usw_opf_alloc_offset(lchip, &opf, mem_num, &mem_base);
            if (ret == CTC_E_NO_RESOURCE)
            {
                _sys_usw_linkagg_fragment(lchip);
                /*need to update member base after linkagg fragment*/
                old_group.member_base = p_src_group->member_base;
                ret = sys_usw_opf_alloc_offset(lchip, &opf, mem_num, &mem_base);
            }
        }

        CTC_ERROR_GOTO(ret, ret, error_proc_0);

        p_src_group->max_member_num = is_alloc_en ? mem_num : old_group.max_member_num;
        p_src_group->member_base =  is_alloc_en ? mem_base:old_group.member_base;

        if((!(flag & SYS_LAG_REP_FIXED_MEM)) && (mem_num == 0))
        {
            p_src_group->max_member_num  = 0;
            p_src_group->port_list = NULL;
        }
    }
    p_src_group->real_member_num = 0;
    p_src_group->local_port_cnt = 0;
    p_src_group->port_cnt = 0;
    if(p_src_group->max_member_num)
    {
       uint16 port_list_num = p_src_group->mode == CTC_LINKAGG_MODE_DLB ? MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM) : mem_num;
       p_src_group->port_list = mem_malloc(MEM_LINKAGG_MODULE, port_list_num * sizeof(void*));
       if(!p_src_group->port_list)
       {
           ret = CTC_E_NO_MEMORY;
           goto error_proc_1;
       }
       sal_memset(p_src_group->port_list, 0, port_list_num * sizeof(void*));
    }

    /*3. add new ports */
    /*if flag ==SYS_LAG_REP_MEM_LAG, indictae replace linkagg group,remain port old property */
    p_src_group->is_lag = flag & SYS_LAG_REP_MEM_LAG ? 1 : 0;
   
    /*ELOOP port replace for uc, used in VxLAN mlag replace*/
    if (!p_src_group->is_lag && mem_num == 1 &&  sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gport[0])) && !DRV_FROM_AT(lchip))
    {
        uint32 channel_id = 0;
        cmd = DRV_IOR(DsQWriteDestPortChannelMap_t, DsQWriteDestPortChannelMap_channelId_f);
        DRV_FIELD_IOCTL(lchip, CTC_MAP_GPORT_TO_LPORT(gport[0]), cmd, &channel_id);
        channel_id = channel_id%MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
        p_src_group->is_lag = (channel_id >=  MCHIP_CAP(SYS_CAP_CHANID_ELOOP) && (channel_id  < MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_CHANID_LOOP_NUM)));

    }

    for (loop = 0; loop < mem_num; loop ++)
    {
        CTC_ERROR_GOTO(_sys_usw_linkagg_add_port(lchip, p_src_group,gport[loop], 0, 0,1), ret , error_proc_1);

    }

    if (old_group.mode == CTC_LINKAGG_MODE_DLB)
    {
        if (DRV_FROM_TMM(lchip))
        {
            _sys_usw_linkagg_reverve_member(lchip, p_src_group->tid, mem_num);
        }

        _sys_usw_linkagg_update_dlb_flow(lchip, p_src_group, gport, mem_num);
    }

    /*4.replace bitmap and mask for mc, MLAG replace only update uc*/
    if ((MCHIP_LAG(lchip)->replace_nonuc_ports) && (!p_src_group->is_lag) && (!CTC_FLAG_ISSET(p_src_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH)))
    {
        MCHIP_LAG(lchip)->replace_nonuc_ports(lchip, p_src_group);
    }

    /*5. change memer base */
    cmd = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_src_group->tid, cmd, &ds_linkagg_group);
    SetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_linkagg_group, p_src_group->member_base);
    SetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_linkagg_group, p_src_group->real_member_num);
    cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_src_group->tid, cmd, &ds_linkagg_group);

    /*6. set the old non-linkagg member is normal port,if old_group.is_lag!=0,
    indicte the last operation is replace linkagg group,remain port old property */
    loop = 0;
    if(old_group.is_lag && old_group.mode != CTC_LINKAGG_MODE_DLB)
    {
        loop = old_group.port_cnt;
    }

    for (; loop < old_group.port_cnt; loop ++)
    {
        tmp = old_group.port_list[loop]->gport;
        if(!old_group.port_list[loop]->valid
                                    &&  sys_usw_chip_is_local(lchip, (SYS_MAP_CTC_GPORT_TO_GCHIP(tmp))))
        {
            /* clear backup port */
            if (MCHIP_LAG(lchip)->set_lsh)
            {
                ctc_linkagg_lsh_t port_array;
                sal_memset(&port_array, 0, sizeof(port_array));
                MCHIP_LAG(lchip)->set_lsh(lchip, &old_group, tmp, &port_array);
            }

            if(old_group.mode == CTC_LINKAGG_MODE_DLB || CTC_FLAG_ISSET(old_group.flag, CTC_LINKAGG_GROUP_FLAG_SPM_EN))
            {
                _sys_usw_del_member_channel(lchip, p_src_group->tid, tmp);
            }
            if(old_group.is_lag)
            {
                continue;
            }
           if(!p_usw_linkagg_master[lchip]->bind_gport_disable
            && (!CTC_FLAG_ISSET(p_src_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) || (tid< MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))))
           {
              sys_usw_port_api_set_global_port(lchip, CTC_MAP_GPORT_TO_LPORT(tmp), tmp, FALSE);
           }
           if (!CTC_FLAG_ISSET(p_src_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) || (tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)))
           {
               sys_usw_port_api_update_mc_linkagg(lchip, p_src_group->tid, CTC_MAP_GPORT_TO_LPORT(tmp), FALSE);
           }
        }
    }
    /*7. free old  member */
    if(old_group.max_member_num && !(flag & SYS_LAG_REP_FIXED_MEM)
        && (old_group.port_cnt !=0  || mem_num ==0 || mem_num > old_group.max_member_num  ) && p_src_group->mode != CTC_LINKAGG_MODE_DLB)
    {
        sys_usw_opf_free_offset(lchip, &opf, old_group.max_member_num, old_group.member_base);
    }
    for (loop = 0; loop < old_group.port_cnt; loop++ )
    {
        mem_free(old_group.port_list[loop]);
    }
    mem_free(old_group.port_list);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    return ret;
error_proc_1:
    if (p_src_group->port_list)
    {
       uint16 port_list_num = p_src_group->mode == CTC_LINKAGG_MODE_DLB ? MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM) : p_src_group->port_cnt;
       for (loop = 0; loop < port_list_num; loop++ )
       {
           mem_free(p_src_group->port_list[loop]);
       }
        mem_free(p_src_group->port_list)  ;
    }

    if(is_alloc_en)
    {
        sys_usw_opf_free_offset(lchip, &opf, p_src_group->max_member_num, p_src_group->member_base);
    }

    /*recover old group*/
    sal_memcpy(p_src_group,&old_group, sizeof(old_group));
error_proc_0:
    return ret;
}

int32
sys_usw_linkagg_replace_ports(uint8 lchip, uint16 tid, uint32* gport, uint16 mem_num)
{
    int32 ret = 0;
    sys_linkagg_t* p_dst_group = NULL;
    uint16 mem_idx = 0;
    uint32 flag = 0;
    uint8  member_cnt = 0;
    uint32 member_list[SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX] = {0};
    sys_linkagg_t* p_group = NULL;
    uint8 mirror_ref_cnt = 0;
    /* sanity check */
    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(gport);
    LINKAGG_LOCK;

    if (CTC_IS_LINKAGG_PORT(gport[0]))
    {
        /*mlag ,and get ports*/
        uint32* new_gport;
        p_dst_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, CTC_MAP_GPORT_TO_LPORT(gport[0]));
        if(!p_dst_group || !p_dst_group->real_member_num)
        {
           SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Entry is not exist \n");
           LINKAGG_UNLOCK;
           return CTC_E_NOT_EXIST;
        }

        new_gport = mem_malloc(MEM_LINKAGG_MODULE, p_dst_group->real_member_num*sizeof(uint32));
        if (!new_gport)
        {
          LINKAGG_UNLOCK;
          return  CTC_E_NO_MEMORY;
        }
        for (mem_idx = 0; mem_idx < p_dst_group->real_member_num ; mem_idx++)
        {
           new_gport[mem_idx] = p_dst_group->port_list[mem_idx]->gport;
        }
        flag = SYS_LAG_REP_MEM_LAG;
        flag |= (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX) ?0: SYS_LAG_REP_FIXED_MEM;
        ret =  _sys_usw_linkagg_replace_ports( lchip,  tid,  new_gport, p_dst_group->real_member_num,flag);
        mem_free(new_gport);
    }
    else
    {
        flag = (p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX) ?0: SYS_LAG_REP_FIXED_MEM;
        ret =  _sys_usw_linkagg_replace_ports( lchip,  tid,  gport, mem_num,flag);
    }

    if(MCHIP_LAG(lchip)->update_mirror_dest && CTC_E_NONE == ret)
    {
        ret = MCHIP_LAG(lchip)->update_mirror_dest(lchip, tid, 1);
        LINKAGG_UNLOCK;
        return ret;
    }

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (p_group && p_group->mirror_ref_cnt && ret == CTC_E_NONE)
    {
        mirror_ref_cnt = p_group->mirror_ref_cnt;
        member_cnt = SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX;
        ret = _sys_usw_linkagg_get_ports2(lchip, p_group, member_list, &member_cnt);
    }
    LINKAGG_UNLOCK;
    if (ret == CTC_E_NONE && mirror_ref_cnt)
    {
        SYS_CB(SYS_CB_MIRROR_SET_DST_TO_LINKAGG, lchip, tid, member_list, member_cnt, 1);
    }
     return ret;

}

int32
sys_usw_linkagg_set_lsh(uint8 lchip, uint16 tid, uint32 fail_port, ctc_linkagg_lsh_t* port_array)
{
    int32 ret = CTC_E_NONE;
    uint8 dest_chip_id = 0;
    sys_linkagg_t* p_group = NULL;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_PTR_VALID_CHECK(port_array);
    SYS_LINKAGG_INIT_CHECK();
    dest_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(fail_port);
    if (FALSE == sys_usw_chip_is_local(lchip, dest_chip_id))
    {
        return CTC_E_INVALID_PARAM;
    }

    if(port_array->lsh_mode == CTC_LINKAGG_LSH_MODE_USERDEF)
    {
        uint8 loop = 0;
        CTC_MAX_VALUE_CHECK(port_array->count, SYS_LINKAGG_LSH_PORTS_MAX);
        for (loop = 0; loop < port_array->count; loop++)
        {
            if CTC_IS_LINKAGG_PORT(port_array->backup_ports[loop])
            {
                return CTC_E_INVALID_PARAM;
            }
        }
    }
    LINKAGG_LOCK;
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto out;
    }
    if(p_group->mode == CTC_LINKAGG_MODE_DLB)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "dlb mode no support link selfhealing!\n");
        ret = CTC_E_INVALID_PARAM;
        goto out;
    }
    if (MCHIP_LAG(lchip)->set_lsh)
    {
        CTC_ERROR_GOTO(MCHIP_LAG(lchip)->set_lsh(lchip, p_group, fail_port, port_array), ret, out);
    }
out:
    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_get_lsh(uint8 lchip, uint16 tid, uint32 fail_port,ctc_linkagg_lsh_t* port_array)
{
    PortLagLinkSelfHealingSet_m uc_self_healing;
    sys_linkagg_t* p_group = NULL;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint8  step = 0;
    uint8  valid = 0;
    uint8  loop = 0;
    uint8  dest_chip_id = 0;
    uint16 dest_id;
    uint16 lport = 0;
    uint32 value[32] = {0};
    uint16 index = 0;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    dest_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(fail_port);
    lport = CTC_MAP_GPORT_TO_LPORT(fail_port);

    if (FALSE == sys_usw_chip_is_local(lchip, dest_chip_id))
    {
        return CTC_E_INVALID_PARAM;
    }
    if (port_array->count > SYS_LINKAGG_LSH_PORTS_MAX )
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] The number of backup port list reach Max, set fail!\n");
        return CTC_E_INVALID_PARAM;
    }
    SYS_LINKAGG_INIT_CHECK();
    LINKAGG_LOCK;

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        ret =  CTC_E_NOT_EXIST;
        goto out;
    }

    if(TRUE != _sys_usw_linkagg_port_is_member(lchip, p_group, fail_port, &index, NULL))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] The port 0x%x is not a linkagg member!\n",fail_port);
        ret = CTC_E_INVALID_PARAM;
        goto out;
    }

    cmd = DRV_IOR(PortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_IOCTL(lchip, lport, cmd, &uc_self_healing),
                                 p_usw_linkagg_master[lchip]->p_linkagg_mutex);


    cmd = DRV_IOR(PortLagLinkSelfHealingEn_t, PortLagLinkSelfHealingEn_enableBitmap_f);
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_FIELD_IOCTL(lchip, 0, cmd, &value),
                                 p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    valid = CTC_IS_BIT_SET(value[lport / 32], lport % 32);
    port_array->count = valid ? (GetPortLagLinkSelfHealingSet(V, setSize_f, &uc_self_healing) + 1): 0;

    step = PortLagLinkSelfHealingSet_gMember_1_destChipId_f  - PortLagLinkSelfHealingSet_gMember_0_destChipId_f;
    for (loop = 0; loop < port_array->count; loop++)
    {
        dest_chip_id =  DRV_GET_FIELD_V(lchip, PortLagLinkSelfHealingSet_t,
                                        PortLagLinkSelfHealingSet_gMember_0_destChipId_f + loop * step,  &uc_self_healing);
        dest_id = DRV_GET_FIELD_V(lchip, PortLagLinkSelfHealingSet_t,
                                  PortLagLinkSelfHealingSet_gMember_0_destId_f + loop * step, &uc_self_healing);
        port_array->backup_ports[loop] = CTC_MAP_LPORT_TO_GPORT(dest_chip_id, dest_id) ;
    }
out:
    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_get_group_info(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp)
{
    int32  ret = CTC_E_NONE;
    sys_linkagg_t* p_group = NULL;

    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_linkagg_grp);

    LINKAGG_LOCK;
    /* check exist */
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, p_linkagg_grp->tid);
    if(p_group == NULL)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto error_proc;
    }
    p_linkagg_grp->linkagg_mode = p_group->mode;
    p_linkagg_grp->flag = p_group->flag;
    p_linkagg_grp->member_num = p_group->max_member_num;
error_proc:
    LINKAGG_UNLOCK;
    return ret;
}

int32
sys_usw_linkagg_dlb_set_config(uint8 lchip, void* p_cfg)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 chan_id = 0;
    uint16 step = 0;
    ctc_global_lag_dlb_property_t* p_dlb_cfg = (ctc_global_lag_dlb_property_t*)p_cfg;
    ds_t ds;

    CTC_PTR_VALID_CHECK(p_dlb_cfg);
    CTC_MAX_VALUE_CHECK(p_dlb_cfg->port_weight, 0xF);
    CTC_MAX_VALUE_CHECK((p_dlb_cfg->interval * 156250 / 1000), 0xFFFF); 

    if(p_dlb_cfg->interval)
    {
        CTC_ERROR_RETURN(_sys_usw_linkagg_dlb_set_load_quality_threshold(lchip, 125 * p_dlb_cfg->interval));
        /* Config load pulse timer for Tp, [23:8] pulse : [7:0] pulse_frac */
        field_val = (p_dlb_cfg->interval * 156250 / 1000) << 8 | (p_dlb_cfg->interval * 156250 % 1000 * 256 / 1000);
        cmd = DRV_IOR(RefDivLinkAggDrePulse_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        SetRefDivLinkAggDrePulse(V, cfgRefDivLinkAggDrePulse_f, &ds, field_val);
        SetRefDivLinkAggDrePulse(V, cfgResetDivLinkAggDrePulse_f, &ds, 0);
        cmd = DRV_IOW(RefDivLinkAggDrePulse_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }

    /*config load dre shift*/
    step = LagEngineDreTimerCtl_array_1_chanDreDiscountShift_f - LagEngineDreTimerCtl_array_0_chanDreDiscountShift_f;
    cmd = DRV_IOR(LagEngineDreTimerCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    for (chan_id = 0; chan_id < MCHIP_CAP(SYS_CAP_NETWORK_CHANNEL_NUM); chan_id++)
    {
        SetLagEngineDreTimerCtl(V, array_0_chanDreDiscountShift_f + step * chan_id, &ds, p_dlb_cfg->port_weight);
    }
    cmd = DRV_IOW(LagEngineDreTimerCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    return CTC_E_NONE;
}

int32
sys_usw_linkagg_dlb_get_config(uint8 lchip, void* p_cfg)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    ctc_global_lag_dlb_property_t* p_dlb_cfg = (ctc_global_lag_dlb_property_t*)p_cfg;
    ds_t ds;

    CTC_PTR_VALID_CHECK(p_dlb_cfg);

    /*get Tp*/
    cmd = DRV_IOR(RefDivLinkAggDrePulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    field_val = GetRefDivLinkAggDrePulse(V, cfgRefDivLinkAggDrePulse_f, &ds);
    p_dlb_cfg->interval = ((field_val >> 8) * 1000 + (field_val & 0xFF) * 1000 / 256) / 156250;

    cmd = DRV_IOR(LagEngineDreTimerCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    p_dlb_cfg->port_weight = GetLagEngineDreTimerCtl(V, array_0_chanDreDiscountShift_f, &ds);

    return CTC_E_NONE;
}


#define __CHANNEL_AGG__
STATIC int32
_sys_usw_linkagg_get_channel_agg_group(uint8 lchip, uint16 chan_id, uint8* chanagg_id)
{
    uint8 grp_index = 0;
    uint16 mem_index = 0;
    uint32 chanagg_grp_num = 0;
    uint32 cmd = 0;
    uint32 mem_num = 0;
    uint32 mem_base = 0;
    uint32 mem_channel_id = 0;

    sys_usw_ftm_query_table_entry_num(lchip, DsLinkAggregateChannelGroup_t, &chanagg_grp_num);
    for (grp_index = 0; grp_index < chanagg_grp_num; grp_index++)
    {
        cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DsLinkAggregateChannelGroup_channelLinkAggMemNum_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, grp_index, cmd, &mem_num));
        if(mem_num == 0)
        {
            continue;
        }
        cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DsLinkAggregateChannelGroup_channelLinkAggMemBase_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, grp_index, cmd, &mem_base));
        for (mem_index = mem_base; mem_index < (mem_base + mem_num); mem_index++)
        {
            cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mem_index, cmd, &mem_channel_id));
            if (chan_id == mem_channel_id)
            {
                *chanagg_id = grp_index;
                return CTC_E_NONE;
            }
        }
    }
    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_get_channel_agg_ref_cnt(uint8 lchip, uint8 tid, uint8* ref_cnt)
{
    sys_linkagg_t* p_chanagg = NULL;

    if ((tid > MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1) || (0 == tid))
    {
        return CTC_E_INVALID_PARAM;
    }
    p_chanagg = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, tid);
    if (NULL == p_chanagg)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Chanagg Not Exist!\n");
        return CTC_E_NOT_EXIST;
    }
    *ref_cnt = p_chanagg->ref_cnt;
    return CTC_E_NONE;
}

int32
sys_usw_linkagg_get_channel_agg_info(uint8 lchip, uint32 chan_id, uint8* chanagg_id, uint8* chanagg_ref_cnt)
{
    int32 ret = CTC_E_NONE;
    SYS_LINKAGG_INIT_CHECK();

    LINKAGG_LOCK;
    CTC_ERROR_GOTO(_sys_usw_linkagg_get_channel_agg_group(lchip, chan_id, chanagg_id), ret, roll_back_0);
    if (*chanagg_id)
    {
        CTC_ERROR_GOTO(_sys_usw_linkagg_get_channel_agg_ref_cnt(lchip, *chanagg_id, chanagg_ref_cnt), ret, roll_back_0);
    }
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Channel agg group:%d, ref_cnt:%d!\n", *chanagg_id, *chanagg_ref_cnt);
roll_back_0:
    LINKAGG_UNLOCK;
    return ret;
}

int32
_sys_usw_linkagg_set_channel_property(uint8 lchip, uint8 tid, uint32 value)
{
    uint32 cmd = 0;
    DsLinkAggregateChannelGroup_m ds_linkagg_group;
    sal_memset(&ds_linkagg_group,0,sizeof(DsLinkAggregateChannelGroup_m));
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd, &ds_linkagg_group));
    SetDsLinkAggregateChannelGroup(V, hashOffset_f, &ds_linkagg_group, value % 16);
    SetDsLinkAggregateChannelGroup(V, hashSelect_f, &ds_linkagg_group, value / 16);
    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, tid, cmd, &ds_linkagg_group));
    return CTC_E_NONE;
}

int32
sys_usw_linkagg_set_channel_agg_ref_cnt(uint8 lchip, uint8 tid, bool is_add)
{
    int32 ret = CTC_E_NONE;
    sys_linkagg_t* p_chanagg = NULL;

    SYS_LINKAGG_INIT_CHECK();
    if ((tid > MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1) || (0 == tid))
    {
        return CTC_E_INVALID_PARAM;
    }
    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP, 1);
    p_chanagg = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, tid);
    if (NULL == p_chanagg)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Chanagg Not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto OUT;
    }
    if (is_add)
    {
        p_chanagg->ref_cnt++;
    }
    else
    {
        p_chanagg->ref_cnt = p_chanagg->ref_cnt? (p_chanagg->ref_cnt - 1) : 0;
    }
OUT:
    LINKAGG_UNLOCK;
    return ret;
}

STATIC int32
_sys_usw_linkagg_update_channel_table(uint8 lchip, sys_linkagg_mem_t* p_chankagg,  bool is_add_port, uint16 port_index)
{
    uint32 cmd = 0;
    uint32 mem_base = 0;
    DsLinkAggregateChannelMember_m ds_chanagg_member;
    DsLinkAggregateChannelGroup_m ds_chanagg_group;
    uint16 tail_index = 0;
    uint16 port_cnt=0;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&ds_chanagg_member, 0, sizeof(DsLinkAggregateChannelMember_m));
    sal_memset(&ds_chanagg_group, 0, sizeof(DsLinkAggregateChannelGroup_m));

    mem_base = p_chankagg->tid * MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_PER_GRP_MEM);
    tail_index = p_chankagg->port_cnt;
    port_cnt = p_chankagg->port_cnt;

    if (TRUE == is_add_port)
    {
        /*update member */
        SetDsLinkAggregateChannelMember(V, channelId_f, &ds_chanagg_member, SYS_USW_CHANNEL_ENCODE(p_chankagg->gport));
        cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (mem_base + port_index), cmd, &ds_chanagg_member));

        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Write DsLinkAggregateChannelMember %d\n", (mem_base + port_index));

        /* update group member cnt */
        cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_chankagg->tid, cmd, &ds_chanagg_group));
        SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_chanagg_group, port_cnt);
        SetDsLinkAggregateChannelGroup(V, grpNotEmpty_f, &ds_chanagg_group, 1);
        cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_chankagg->tid, cmd, &ds_chanagg_group));
    }
    else
    {
        /* update group member cnt */
        cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_chankagg->tid, cmd, &ds_chanagg_group));
        SetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &ds_chanagg_group, port_cnt);
        SetDsLinkAggregateChannelGroup(V, grpNotEmpty_f, &ds_chanagg_group, port_cnt?1:0);
        cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_chankagg->tid, cmd, &ds_chanagg_group));

        if (0 == p_chankagg->port_cnt)
        {
            cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip,  (mem_base + port_index), cmd, &ds_chanagg_member));
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Clear DsLinkAggregateChannelMember %d\n",(mem_base + port_index));
        }
        else
        {
            /*copy the last one to the removed port position,and remove member port from linkagg at tail*/
            cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip,  (mem_base + tail_index), cmd, &ds_chanagg_member));
            cmd = DRV_IOW(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip,  (mem_base + port_index), cmd, &ds_chanagg_member));
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Copy DsLinkAggregateChannelMember from %d to %d\n",  (mem_base + tail_index), (mem_base + port_index));
        }
    }

    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_create_channel_agg(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp)
{
    uint32 cmd = 0;
    int32  ret = CTC_E_NONE;
    uint16 mem_num = 0;
    uint16 mem_base = 0;
    DsLinkAggregateChannelGroup_m ds_chanagg_group;
    sys_linkagg_t* p_chan_group = NULL;

    /* check exist */
    p_chan_group = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, p_linkagg_grp->tid);
    if (p_chan_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Chanagg Has Exist!\n");
        ret = CTC_E_EXIST;
        goto error_0;
    }

    /* init linkAgg group info */
    p_chan_group = mem_malloc(MEM_LINKAGG_MODULE, sizeof(sys_linkagg_t));
    if(!p_chan_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "No memory!\n");
        ret = CTC_E_NO_MEMORY;
        goto error_0;
    }

    mem_num = MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_PER_GRP_MEM);
    mem_base = p_linkagg_grp->tid * mem_num;

    sal_memset(p_chan_group, 0, sizeof(sys_linkagg_t));
    p_chan_group->tid = p_linkagg_grp->tid;
    p_chan_group->mode = CTC_LINKAGG_MODE_STATIC;
    p_chan_group->member_base = mem_base;
    p_chan_group->max_member_num = mem_num;

    if (!ctc_vector_add(p_usw_linkagg_master[lchip]->chan_group, p_chan_group->tid, p_chan_group))
    {
        ret = CTC_E_NO_MEMORY;
        goto error_1;
    }

    sal_memset(&ds_chanagg_group, 0, sizeof(ds_chanagg_group));
    SetDsLinkAggregateChannelGroup(V, channelLinkAggMemBase_f, &ds_chanagg_group, mem_base);
    SetDsLinkAggregateChannelGroup(V, hashOffset_f, &ds_chanagg_group, 0);
    SetDsLinkAggregateChannelGroup(V, hashSelect_f, &ds_chanagg_group, MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM) == SYS_USW_LB_HASH_CTL_NUM ? 2 : 1);
    /*not support if needed
    if (CTC_FLAG_ISSET(p_linkagg_grp->flag, CTC_LINKAGG_GROUP_FLAG_LB_HASH_OFFSET_VALID))
    {
        SetDsLinkAggregateChannelGroup(V, hashCfgPriorityIsHigher_f, &ds_chanagg_group, 1);
        SetDsLinkAggregateChannelGroup(V, hashOffset_f, &ds_chanagg_group, (p_linkagg_grp->lb_hash_offset % 16));
        SetDsLinkAggregateChannelGroup(V, hashSelect_f, &ds_chanagg_group, (p_linkagg_grp->lb_hash_offset / 16));
    }
    */
    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    if ((ret = DRV_IOCTL(lchip, p_linkagg_grp->tid, cmd, &ds_chanagg_group)) < 0)
    {
        SYS_LINKAGG_GOTO_ERROR(ret, error_2);
    }

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Groupid = %d, mem_base = %d!\n", p_linkagg_grp->tid, mem_base);

    return CTC_E_NONE;

error_2:
   ctc_vector_del(p_usw_linkagg_master[lchip]->chan_group, p_chan_group->tid);
error_1:
    mem_free(p_chan_group);
error_0:
    return ret;
}

int32
_sys_usw_linkagg_destroy_channel_agg(uint8 lchip, uint8 tid)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 cmd_uc = 0;
    uint32 cmd_mc = 0;
    uint32 field_val = 0;
    DsLinkAggregateChannelGroup_m ds_chanagg_group;
    sys_linkagg_t* p_group = NULL;
    uint8 index = 0;
    uint8  mem_num = 0;
    uint16 chanagg_base=0;
    uint32 chan_id = 0;
    uint16 lport = 0;
    uint32 mem_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};

    /*do remove*/
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto OUT;
    }

    /*update for bpe*/
    SYS_CB(SYS_CB_BPE_UPDATE_NON_UC_CHAN_AGG_MEM, lchip, tid, mem_bmp, 1);

    /*reset linkagg member*/
    sal_memset(&ds_chanagg_group, 0, sizeof(ds_chanagg_group));
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &ds_chanagg_group), ret, OUT);

    chanagg_base=GetDsLinkAggregateChannelGroup(V,channelLinkAggMemBase_f,&ds_chanagg_group);
    mem_num=GetDsLinkAggregateChannelGroup(V,channelLinkAggMemNum_f,&ds_chanagg_group);
    cmd = DRV_IOR(DsLinkAggregateChannelMember_t, DsLinkAggregateChannelMember_channelId_f);
    cmd_uc = DRV_IOW(DsPortChannelLag_t, DsPortChannelLag_linkAggregationChannelGroup_f);
    cmd_mc = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_chanLagEnable_f);
    for (index = 0; index < mem_num; index++)
    {
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, index + chanagg_base, cmd, &chan_id), ret, OUT);
        lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, chan_id);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd_uc, &field_val), ret, OUT);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd_mc, &field_val), ret, OUT);
    }

    /*reset linkagg group */
    sal_memset(&ds_chanagg_group, 0, sizeof(ds_chanagg_group));

    cmd = DRV_IOW(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    if ((ret = DRV_IOCTL(lchip, tid, cmd, &ds_chanagg_group)) < 0)
    {
        ret = CTC_E_HW_FAIL;
        goto OUT;
    }

    ctc_vector_del(p_usw_linkagg_master[lchip]->chan_group, tid);

    mem_free(p_group);
OUT:
    return ret;
}

int32
sys_usw_linkagg_create_channel_agg(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp)
{
    int32 ret = CTC_E_NONE;

    /* sanity check */
    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_linkagg_grp);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "ChanAggId = 0x%x\n", p_linkagg_grp->tid);

    if ((p_linkagg_grp->tid > MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1) || (0 == p_linkagg_grp->tid))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");
        return CTC_E_BADID;
    }

    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP, 1);
    ret = _sys_usw_linkagg_create_channel_agg(lchip, p_linkagg_grp);
    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_destroy_channel_agg(uint8 lchip, uint8 tid)
{
    int32 ret = CTC_E_NONE;

    /* sanity check */
    SYS_LINKAGG_INIT_CHECK();

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "ChanAggId = 0x%x\n", tid);

    if ((tid > MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1) || (0 == tid))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");
        return CTC_E_BADID;
    }

    LINKAGG_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    ret = _sys_usw_linkagg_destroy_channel_agg(lchip, tid);
    LINKAGG_UNLOCK;

    return ret;
}

int32
_sys_usw_linkagg_add_channel_member(uint8 lchip, uint8 tid, uint32 chan_id)
{
    int32 ret = CTC_E_NONE;
    uint16 index = 0;
    sys_linkagg_mem_t  chan_agg_member;
    uint16 mem_num = 0;
    uint16 chanagg_base=0;
    uint32 chan_id_temp = 0;
    uint32 cmd=0;
    uint32 cmd_member=0;
    uint32 mem_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
    sys_linkagg_t* p_group = NULL;
    DsLinkAggregateChannelGroup_m ds_chanagg_group;
    DsLinkAggregateChannelMember_m ds_chanagg_member;

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, tid);
    if (!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Chanagg Not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto OUT;
    }

    /*check exist*/
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    cmd_member = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);

    sal_memset(&ds_chanagg_group, 0, sizeof(ds_chanagg_group));
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &ds_chanagg_group), ret, OUT);

    chanagg_base=GetDsLinkAggregateChannelGroup(V,channelLinkAggMemBase_f,&ds_chanagg_group);
    mem_num=GetDsLinkAggregateChannelGroup(V,channelLinkAggMemNum_f,&ds_chanagg_group);
    sal_memset(&ds_chanagg_member, 0, sizeof(ds_chanagg_member));
    for (index = chanagg_base; index < (mem_num + chanagg_base); index++)
    {
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd_member, &ds_chanagg_member), ret, OUT);
        chan_id_temp = GetDsLinkAggregateChannelMember(V, channelId_f, &ds_chanagg_member);
        if (chan_id_temp == chan_id)
        {
            ret = CTC_E_EXIST;
            goto OUT;
        }
        CTC_BMP_SET(mem_bmp, chan_id_temp);
    }

    /*get the first unused pos*/
    index = p_group->real_member_num;

    sal_memset(&chan_agg_member, 0, sizeof(chan_agg_member));
    chan_agg_member.tid = tid;
    chan_agg_member.gport = chan_id;
    chan_agg_member.mem_valid_num = p_group->real_member_num;
    if ((chan_agg_member.mem_valid_num >= MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_PER_GRP_MEM)))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Chanagg mem valid num error!\n");
        ret = CTC_E_INVALID_PARAM;
        goto OUT;
    }

    chan_agg_member.mem_valid_num++;
    chan_agg_member.port_cnt = chan_agg_member.mem_valid_num;
    /*write asic table*/
    CTC_ERROR_GOTO(_sys_usw_linkagg_update_channel_table(lchip, &chan_agg_member, TRUE, index), ret, OUT);

    if (DRV_FROM_TMM(lchip))
    {
        if(MCHIP_LAG(lchip)->channel_update_nonuc_ports)
        {
            CTC_ERROR_GOTO(MCHIP_LAG(lchip)->channel_update_nonuc_ports(lchip, 1, chan_id, mem_bmp), ret, OUT);
        }
    }

    p_group->real_member_num++;

OUT:
    return ret;

}

int32
sys_usw_linkagg_add_channel(uint8 lchip, uint8 tid, uint32 gport)
{
    int32 ret = CTC_E_NONE;
    uint8 gchip = 0;
    DsPortChannelLag_m ds_chanagg_grp;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint32 chan_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    /*Sanity check*/
    SYS_LINKAGG_INIT_CHECK();
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "ChanAggId: 0x%x,mem_port: 0x%x\n", tid, gport);

    if ((tid > MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1) || (0 == tid))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");
        return CTC_E_BADID;
    }

    SYS_GLOBAL_PORT_CHECK(gport);
    gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(gport);
    SYS_GLOBAL_CHIPID_CHECK(gchip);
    if (FALSE == sys_usw_chip_is_local(lchip, gchip))
    {
        return CTC_E_INVALID_CHIP_ID;
    }

    /*do add*/
    LINKAGG_LOCK;
    dmps_port_info.gport = gport;
    CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), ret, OUT);
    if (SYS_DMPS_RSV_PORT == sys_usw_is_network_port(lchip, gport))
    {
        sys_usw_get_channel_by_port(lchip, gport, (uint16*)&chan_id);
    }
    ret = _sys_usw_linkagg_add_channel_member(lchip, tid, chan_id);
    if ((CTC_E_EXIST != ret) && (ret < 0))
    {
        goto OUT;
    }
    /*write chan lag for unicast*/
    sal_memset(&ds_chanagg_grp, 0, sizeof(ds_chanagg_grp));
    SetDsPortChannelLag(V, linkAggregationChannelGroup_f, &ds_chanagg_grp, tid);
    cmd = DRV_IOW(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport), cmd, &ds_chanagg_grp), ret, OUT);

    /*write chan lag for multicast*/
    field_val = 1;
    cmd = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_chanLagEnable_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport), cmd, &field_val), ret, OUT);

    /*update chan lag for bpe*/
    if (SYS_CB_PTR(SYS_CB_BPE_UPDATE_NON_UC_CHAN_AGG_MEM))
    {
        DsMetPortChannelLag_m ds_met_chan_grp;
        uint32 mem_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};

        cmd = DRV_IOR(DsMetPortChannelLag_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport), cmd, &ds_met_chan_grp), ret, OUT);
        GetDsMetPortChannelLag(A, channelBitmap_f, &ds_met_chan_grp, mem_bmp);
        CTC_ERROR_GOTO(SYS_CB(SYS_CB_BPE_UPDATE_NON_UC_CHAN_AGG_MEM, lchip, tid, mem_bmp, 0), ret, OUT);
    }

OUT:
    LINKAGG_UNLOCK;
    return ret;
}

int32
_sys_usw_linkagg_remove_channel_member(uint8 lchip, uint8 tid, uint32 chan_id)
{
    uint16 loop = 0;
    uint16 index = 0;
    uint8 find = 0;
    uint16 mem_num = 0;
    uint16 chanagg_base=0;
    uint32 chan_id_temp = 0;
    uint32 cmd=0;
    uint32 cmd_member=0;
    uint32 mem_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
    sys_linkagg_mem_t p_chanagg;
    sys_linkagg_t* p_group = NULL;
    DsLinkAggregateChannelGroup_m ds_chanagg_group;
    DsLinkAggregateChannelMember_m ds_chanagg_member;

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, tid);
    if (!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Chanagg Not Exist!\n");
        return CTC_E_NOT_EXIST;
    }

    /*check if port is a member of linkagg*/
    cmd = DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG);
    cmd_member = DRV_IOR(DsLinkAggregateChannelMember_t, DRV_ENTRY_FLAG);

    sal_memset(&ds_chanagg_group, 0, sizeof(ds_chanagg_group));
    DRV_IOCTL(lchip, tid, cmd, &ds_chanagg_group);

    chanagg_base=GetDsLinkAggregateChannelGroup(V,channelLinkAggMemBase_f,&ds_chanagg_group);
    mem_num=GetDsLinkAggregateChannelGroup(V,channelLinkAggMemNum_f,&ds_chanagg_group);
    sal_memset(&ds_chanagg_member, 0, sizeof(ds_chanagg_member));
    for (loop = chanagg_base; loop < (mem_num + chanagg_base); loop++)
    {
        DRV_IOCTL(lchip, loop, cmd_member, &ds_chanagg_member);
        chan_id_temp = GetDsLinkAggregateChannelMember(V, channelId_f, &ds_chanagg_member);
        if(chan_id_temp == chan_id)
        {
            index = loop - chanagg_base;
            find = 1;
        }
        CTC_BMP_SET(mem_bmp, chan_id_temp);
    }

    if (!find)  /* not find the member*/
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The port is not exist in chanagg group, remove fail!\n");
        return CTC_E_NOT_EXIST;
    }

    sal_memset(&p_chanagg, 0, sizeof(p_chanagg));
    p_chanagg.tid = tid;
    p_chanagg.gport = chan_id;
    p_chanagg.mem_valid_num = p_group->real_member_num;
    if (0 == p_chanagg.mem_valid_num)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The member num of linkagg is zero, remove fail!\n");
        return CTC_E_NOT_EXIST;
    }

    p_chanagg.mem_valid_num--;
    p_chanagg.port_cnt = p_chanagg.mem_valid_num;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "index = %d, port_cnt = %d\n", index,  p_chanagg.port_cnt);

    /*write asic table*/
    _sys_usw_linkagg_update_channel_table(lchip, &p_chanagg, FALSE, index);

    if (DRV_FROM_TMM(lchip))
    {
        if(MCHIP_LAG(lchip)->channel_update_nonuc_ports)
        {
            MCHIP_LAG(lchip)->channel_update_nonuc_ports(lchip, 0, chan_id, mem_bmp);
        }
    }

    p_group->real_member_num--;

    return CTC_E_NONE;
}

int32
sys_usw_linkagg_remove_channel(uint8 lchip, uint8 tid, uint32 gport)
{
    uint8 gchip = 0;
    uint32 cmd=0;
    uint32 field_val = 0;
    uint32 chan_id = 0;
    DsPortChannelLag_m ds_chanagg_grp;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    /*Sanity check*/
    SYS_LINKAGG_INIT_CHECK();
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "linkAggId: 0x%x,mem_port: 0x%x\n", tid, gport);

    if ((tid > MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1) || (0 == tid))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] Tid is invalid \n");
        return CTC_E_BADID;
    }

    SYS_GLOBAL_PORT_CHECK(gport);
    gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(gport);
    SYS_GLOBAL_CHIPID_CHECK(gchip);
    if (FALSE == sys_usw_chip_is_local(lchip, gchip))
    {
        return CTC_E_INVALID_CHIP_ID;
    }
    LINKAGG_LOCK;
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN_WITH_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id), 
                                    p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    if (SYS_DMPS_RSV_PORT == sys_usw_is_network_port(lchip, gport))
    {
        sys_usw_get_channel_by_port(lchip, gport, (uint16*)&chan_id);
    }

    /*update chan lag for bpe*/
    if (SYS_CB_PTR(SYS_CB_BPE_UPDATE_NON_UC_CHAN_AGG_MEM))
    {
        DsMetPortChannelLag_m ds_met_chan_grp;
        uint32 mem_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};

        cmd = DRV_IOR(DsMetPortChannelLag_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport), cmd, &ds_met_chan_grp);
        GetDsMetPortChannelLag(A, channelBitmap_f, &ds_met_chan_grp, mem_bmp);
        CTC_BMP_UNSET(mem_bmp, SYS_USW_CHANNEL_ENCODE(chan_id));
        SYS_CB(SYS_CB_BPE_UPDATE_NON_UC_CHAN_AGG_MEM, lchip, tid, mem_bmp, 0);
    }

    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_linkagg_remove_channel_member(lchip, tid, chan_id),p_usw_linkagg_master[lchip]->p_linkagg_mutex);
    
    /*update chan linkagg for unicast*/
    cmd = DRV_IOW(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    sal_memset(&ds_chanagg_grp, 0, sizeof(ds_chanagg_grp));
    DRV_IOCTL(lchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport), cmd, &ds_chanagg_grp);

    /*disable chan linkagg multicast*/
    field_val = 0;
    cmd = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_chanLagEnable_f);
    DRV_FIELD_IOCTL(lchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport), cmd, &field_val);

    LINKAGG_UNLOCK;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_linkagg_show_node_data(void* node_data, void* user_data)
{
    sys_linkagg_t *p_group = (sys_linkagg_t *)node_data;
    sys_linkagg_stats_t *stats_data = (sys_linkagg_stats_t *)user_data;
    uint8 lchip = 0;

    if ((NULL == p_group) || (NULL == stats_data) 
       || (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && (CTC_MAX_UINT16_VALUE == p_group->member_base)))
    {
        return CTC_E_NONE;
    }

    lchip = stats_data->lchip;

    if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN)
    {
        uint32 cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggFlowNum_f);
        uint32 flow_num = 0;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &flow_num));

        stats_data->static_group_spm_cnt++;
        stats_data->static_group_spm_flow_cnt += _sys_usw_linkagg_driver2flows(lchip, flow_num, 1);
    }
    switch (p_group->mode)
    {
        case CTC_LINKAGG_MODE_STATIC:
        {
            if (p_group->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))
            {
                stats_data->static_group_cnt++;
                if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
                {
                    stats_data->static_group_lmpf_cnt++;
                }

                stats_data->total_group_cnt++;
            }

            stats_data->static_member_cnt += p_group->max_member_num;
            stats_data->total_member_cnt += p_group->max_member_num;

            break;
        }
        case CTC_LINKAGG_MODE_STATIC_FAILOVER:
        {
            if (p_group->tid < MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))
            {
                stats_data->failover_group_cnt++;
                if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)
                {
                    stats_data->failover_group_lmpf_cnt++;
                }
                stats_data->total_group_cnt++;
            }

            stats_data->failover_member_cnt += p_group->max_member_num;
            stats_data->total_member_cnt += p_group->max_member_num;

            break;
        }
        case CTC_LINKAGG_MODE_RR:
        {
            if (p_group->tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))
            {
                break;
            }

            stats_data->rr_group_cnt++;
            if (p_group->flag & CTC_LINKAGG_GROUP_FLAG_RANDOM_RR)
            {
                stats_data->rr_group_random_cnt++;
            }
            stats_data->total_group_cnt++;

            stats_data->rr_member_cnt += p_group->max_member_num;
            stats_data->total_member_cnt += p_group->max_member_num;

            break;
        }
        case CTC_LINKAGG_MODE_DLB:
        {
            if (p_group->tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))
            {
                break;
            }

            stats_data->dynamic_group_cnt++;
            stats_data->total_group_cnt++;

            stats_data->dynamic_member_cnt += p_group->max_member_num;
            if (!DRV_FROM_TMM(lchip))
            {
                stats_data->total_member_cnt += p_group->max_member_num;
            }

            break;
        }
        default:
        {
            break;
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_linkagg_status_show(uint8 lchip)
{
    sys_linkagg_stats_t stats_data;
    uint32 antflow_entry_num = 0;

    SYS_LINKAGG_INIT_CHECK();

    LINKAGG_LOCK;

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------Work Mode--------------------------------\n");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--bind_gport_disable", p_usw_linkagg_master[lchip]->bind_gport_disable);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %s\n", "--linkagg_mode", _sys_usw_linkagg_mode2str(p_usw_linkagg_master[lchip]->linkagg_mode));
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--linkagg_num", MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM));
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--chanagg_grp_num", MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--chanagg_mem_per_grp", MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_PER_GRP_MEM));
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    sal_memset(&stats_data, 0, sizeof(stats_data));
    stats_data.lchip = lchip;
    ctc_vector_traverse(p_usw_linkagg_master[lchip]->group_vector, (vector_traversal_fn)_sys_usw_linkagg_show_node_data, &stats_data);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------Group Resource Usage---------------------------\n");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "ALL Group Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Total count", MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM));
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.total_group_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Free count", MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM) - stats_data.total_group_cnt);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "Static Group Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (All)", stats_data.static_group_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (Lmpf)", stats_data.static_group_lmpf_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "Failover Group Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (All)", stats_data.failover_group_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (Lmpf)", stats_data.failover_group_lmpf_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "RR Group Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (All)", stats_data.rr_group_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (Random)", stats_data.rr_group_random_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "Dynamic Group Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count (All)", stats_data.dynamic_group_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------Member Resource Usage---------------------------\n");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "ALL Member Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Total count", MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM));
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.total_member_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Free count", MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM) - stats_data.total_member_cnt);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "Static Member Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.static_member_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "Failover Member Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.failover_member_cnt);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "RR Member Count");
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.rr_member_cnt);
    if (!DRV_FROM_TMM(lchip))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "Dynamic Member Count");
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.dynamic_member_cnt);
    }
    else
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------Flow Resource Usage---------------------------\n");
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "ALL DLB Flow Count");
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Total count", MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM));
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.dynamic_member_cnt);
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Free count", MCHIP_CAP(SYS_CAP_LINKAGG_DLB_FLOW_NUM) - stats_data.dynamic_member_cnt);

        sys_usw_ftm_query_table_entry_num(lchip, DsAntFlow_t, &antflow_entry_num);
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s\n", "ALL SRV Flow Count");
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Total count", antflow_entry_num);
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Used count", stats_data.static_group_spm_flow_cnt);
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-24s: %u\n", "--Free count", antflow_entry_num - stats_data.static_group_spm_flow_cnt);
    }
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    LINKAGG_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_linkagg_loop_chan_lag_en(uint8 lchip, uint32 enable)
{
    int32 ret = CTC_E_NONE;

    SYS_LINKAGG_INIT_CHECK();
    LINKAGG_LOCK;
    if (MCHIP_LAG(lchip)->loop_chan_lag_en)
    {
        ret =  MCHIP_LAG(lchip)->loop_chan_lag_en(lchip, enable);
    }
    LINKAGG_UNLOCK;

    return ret;
}

int32
_sys_usw_linkagg_wb_mapping_group(uint8 lchip, sys_wb_linkagg_group_t* p_wb_linkagg, sys_linkagg_t* p_linkagg, uint8 sync, uint8 is_chan_agg)
{
    if (sync)
    {
        if (CTC_FLAG_ISSET(p_linkagg->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && (CTC_MAX_UINT16_VALUE == p_linkagg->member_base))
        {
            p_wb_linkagg->tid = p_linkagg->tid+ MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM);
            p_wb_linkagg->max_member_num = p_linkagg->port_cnt;
        }
        else
        {
            p_wb_linkagg->tid = p_linkagg->tid;
            p_wb_linkagg->max_member_num = p_linkagg->max_member_num;
        }
        p_wb_linkagg->flag = p_linkagg->flag;
        p_wb_linkagg->lsh_mode = p_linkagg->lsh_mode;
        p_wb_linkagg->mode = p_linkagg->mode;
        p_wb_linkagg->ref_cnt = p_linkagg->ref_cnt;
        p_wb_linkagg->is_lmpf_cancel = p_linkagg->cfg_lmpf;
        p_wb_linkagg->is_lag = p_linkagg->is_lag;
    }
    else
    {
        uint32 cmd = is_chan_agg ? DRV_IOR(DsLinkAggregateChannelGroup_t, DsLinkAggregateChannelGroup_channelLinkAggMemBase_f)
                    : DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggMemBase_f);

        uint32 mem_base = 0;
        uint32 port_list_num = 0;
        sys_usw_opf_t opf;
        ds_t dslinkagg;
        uint8 is_nonuc_group = 0;

        if (DRV_FROM_TMM(lchip) && CTC_FLAG_ISSET(p_wb_linkagg->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && p_wb_linkagg->tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))
        {
            is_nonuc_group = 1;
        }
        else
        {
            sal_memset(&opf, 0, sizeof(opf));
            opf.pool_type = p_usw_linkagg_master[lchip]->opf_type;

            DRV_FIELD_IOCTL(lchip, p_wb_linkagg->tid, cmd, &mem_base);

            cmd = is_chan_agg ? DRV_IOR(DsLinkAggregateChannelGroup_t, DRV_ENTRY_FLAG):DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, p_wb_linkagg->tid, cmd, &dslinkagg);
        }
        p_linkagg->tid = is_nonuc_group?(p_wb_linkagg->tid-MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)):p_wb_linkagg->tid;
        p_linkagg->flag = p_wb_linkagg->flag;
        p_linkagg->lsh_mode = p_wb_linkagg->lsh_mode;
        p_linkagg->mode = p_wb_linkagg->mode;
        p_linkagg->max_member_num = p_wb_linkagg->max_member_num;
        p_linkagg->ref_cnt = p_wb_linkagg->ref_cnt;
        p_linkagg->real_member_num = is_chan_agg?GetDsLinkAggregateChannelGroup(V, channelLinkAggMemNum_f, &dslinkagg):
            GetDsLinkAggregateGroup(V, linkAggMemNum_f, &dslinkagg);
        p_linkagg->member_base = is_nonuc_group? CTC_MAX_UINT16_VALUE:mem_base;
        p_linkagg->cfg_lmpf = p_wb_linkagg->is_lmpf_cancel;
        p_linkagg->is_lag = p_wb_linkagg->is_lag;
        port_list_num = CTC_LINKAGG_MODE_DLB == p_linkagg->mode ? MCHIP_CAP(SYS_CAP_DLB_MEMBER_NUM) : p_linkagg->max_member_num;
        if (is_chan_agg)
        {
            return CTC_E_NONE;
        }
        if (port_list_num)
        {
            p_linkagg->port_list = mem_malloc(MEM_LINKAGG_MODULE, port_list_num * sizeof(void*));
            if(!p_linkagg->port_list)
            {
                SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                return CTC_E_NO_MEMORY;
            }
            sal_memset(p_linkagg->port_list, 0, port_list_num * sizeof(void*));
        }
        if (is_nonuc_group)
        {
            return CTC_E_NONE;
        }
        if(p_usw_linkagg_master[lchip]->linkagg_mode == CTC_LINKAGG_MODE_FLEX)
        {
            if (!(DRV_FROM_TMM(lchip) && CTC_LINKAGG_MODE_DLB == p_linkagg->mode))
            {
                if(p_linkagg->max_member_num)
                {
                    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset_from_position(lchip, &opf, p_linkagg->max_member_num, p_linkagg->member_base));
                }
            }
            else
            {
                CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset_from_position(lchip, DsLagDlbFlowSetTable_t, 0, p_linkagg->max_member_num, p_linkagg->member_base));
            }
        }
        if(!DRV_IS_DUET2(lchip) && p_linkagg->mode == CTC_LINKAGG_MODE_RR)
        {
            uint32 cmd_rr = DRV_IOR(LagRrProfileIdMappingCtl_t, LagRrProfileIdMappingCtl_rrProfileId_f);
            uint32 rr_profile_id;
            DRV_FIELD_IOCTL(lchip, p_wb_linkagg->tid, cmd_rr, &rr_profile_id);
            CTC_BIT_SET(p_usw_linkagg_master[lchip]->rr_profile_bmp, rr_profile_id);
        }

        if(DRV_FROM_TMM(lchip) && (p_linkagg->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN))
        {
            uint32 cmd = 0;
            uint32 antflow_base = 0;
            uint32 flow_num = 0;
            cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_antFlowTableBase_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_wb_linkagg->tid, cmd, &antflow_base));
            cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggFlowNum_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_wb_linkagg->tid, cmd, &flow_num));
            CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset_from_position(lchip, DsAntFlow_t, 0,
                _sys_usw_linkagg_driver2flows(lchip, flow_num, 1), antflow_base << SYS_LINKAGG_SPM_TBL_BASE_WIDTH));
        }

    }

    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_wb_mapping_member(uint8 lchip, sys_wb_linkagg_member_t* p_wb_linkagg_member, sys_linkagg_t* p_linkagg, uint32* cnt, uint8 is_chan_agg)
{
    uint16 index = 0;
    uint16 tid = 0;

    tid = p_linkagg->tid;

    if (CTC_FLAG_ISSET(p_linkagg->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && DRV_IS_TSINGMA(lchip))
    {
        tid = (p_linkagg->tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))?(p_linkagg->tid-MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)):(p_linkagg->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
    }
    else if (DRV_FROM_TMM(lchip) && CTC_FLAG_ISSET(p_linkagg->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && (CTC_MAX_UINT16_VALUE == p_linkagg->member_base))
    {
        tid = p_linkagg->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM);
    }

    for(index = 0; (index < p_linkagg->port_cnt); index++)
    {
        p_wb_linkagg_member->gport = p_linkagg->port_list[index]->gport;
        p_wb_linkagg_member->tid = tid;
        p_wb_linkagg_member->position = index;
        p_wb_linkagg_member->valid = p_linkagg->port_list[index]->is_local;
        p_wb_linkagg_member->nonuc_block_en = p_linkagg->port_list[index]->nonuc_block_en;
        p_wb_linkagg_member->is_channel_grp = is_chan_agg;
        (*cnt)++;
        p_wb_linkagg_member++;

    }
    return CTC_E_NONE;
}

int32
_sys_usw_linkagg_wb_sync_func(void* array_data, uint32 index, void* user_data)
{
    uint32 max_entry_cnt = 0;
    sys_linkagg_t *p_linkagg = (sys_linkagg_t *)array_data;
    sys_wb_linkagg_group_t  *p_wb_linkagg;
    sys_wb_linkagg_member_t *p_wb_linkagg_member;
    sys_traverse_t *traversal_data = (sys_traverse_t *)user_data;
    ctc_wb_data_t *wb_data = traversal_data->data?(ctc_wb_data_t *)traversal_data->data:(ctc_wb_data_t *)traversal_data->data1;
    uint8 lchip = (uint8)traversal_data->value1;

    max_entry_cnt =  wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    if (traversal_data->data)
    {
        p_wb_linkagg = (sys_wb_linkagg_group_t *)wb_data->buffer + wb_data->valid_cnt;
        sal_memset(p_wb_linkagg, 0, sizeof(sys_wb_linkagg_group_t));
        CTC_ERROR_RETURN(_sys_usw_linkagg_wb_mapping_group(lchip, p_wb_linkagg, p_linkagg, 1, traversal_data->value2));
        wb_data->valid_cnt++;
    }
    else
    {
        p_wb_linkagg_member = (sys_wb_linkagg_member_t*)wb_data->buffer + wb_data->valid_cnt;
        CTC_ERROR_RETURN(_sys_usw_linkagg_wb_mapping_member(lchip, p_wb_linkagg_member, p_linkagg, &wb_data->valid_cnt, traversal_data->value2));
    }

    if (traversal_data->data && wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
sys_usw_linkagg_wb_sync(uint8 lchip,uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    sys_traverse_t user_data = {0};
    sys_wb_linkagg_master_t* p_wb_linkagg_master = NULL;

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    sal_memset(&user_data, 0, sizeof(sys_traverse_t));


    LINKAGG_LOCK;

    user_data.value1 = lchip;
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_LINKAGG_SUBID_MASTER)
    {
        user_data.data = &wb_data;
        /*syncup linkagg master*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_linkagg_master_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER);

        p_wb_linkagg_master = (sys_wb_linkagg_master_t  *)wb_data.buffer;
        sal_memset(wb_data.buffer, 0, sizeof(sys_wb_linkagg_master_t));

        p_wb_linkagg_master->lchip = lchip;
        p_wb_linkagg_master->version = SYS_WB_VERSION_LINKAGG;
        p_wb_linkagg_master->linkagg_mode = p_usw_linkagg_master[lchip]->linkagg_mode;
        p_wb_linkagg_master->tx_load_percent = p_usw_linkagg_master[lchip]->tx_load_percent;
        p_wb_linkagg_master->rsv[0] = 0;
        p_wb_linkagg_master->rsv[1] = 0;

        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_LINKAGG_SUBID_GROUP)
    {
        user_data.data = &wb_data;
        user_data.data1 = NULL;
        /*syncup linkagg group*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_linkagg_group_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP);
        /* is lag group */
        user_data.value2 = 0;

        CTC_ERROR_GOTO(ctc_vector_traverse2(p_usw_linkagg_master[lchip]->group_vector, 0, _sys_usw_linkagg_wb_sync_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP)
    {
        user_data.data = &wb_data;
        user_data.data1 = NULL;
        /*syncup linkagg channel group*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_linkagg_group_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP);
        /* is channel group */
        user_data.value2 = 1;

        CTC_ERROR_GOTO(ctc_vector_traverse2(p_usw_linkagg_master[lchip]->chan_group, 0, _sys_usw_linkagg_wb_sync_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_LINKAGG_SUBID_MEMBER)
    {
        user_data.data = NULL;
        user_data.data1 = &wb_data;
        wb_data.valid_cnt = 0;
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_linkagg_member_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER);
        sal_memset(wb_data.buffer, 0, sizeof(sys_wb_linkagg_member_t) * MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM));
        /* is lag group */
        user_data.value2 = 0;
        CTC_ERROR_GOTO(ctc_vector_traverse2(p_usw_linkagg_master[lchip]->group_vector, 0, _sys_usw_linkagg_wb_sync_func, (void *)&user_data), ret, done);
        /* is channel group */
        user_data.value2 = 1;
        CTC_ERROR_GOTO(ctc_vector_traverse2(p_usw_linkagg_master[lchip]->chan_group, 0, _sys_usw_linkagg_wb_sync_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)  
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER);
    }

done:
    LINKAGG_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

int32
sys_usw_linkagg_wb_restore(uint8 lchip)
{
    uint32 entry_cnt = 0;
    int32 ret = CTC_E_NONE;
    ctc_wb_query_t wb_query;
    sys_wb_linkagg_master_t  wb_linkagg_master;
    sys_wb_linkagg_group_t *wb_linkagg_group = NULL;
    sys_wb_linkagg_member_t *wb_linkagg_member = NULL;
    sys_linkagg_t *p_linkagg;
    sys_linkagg_port_t *port_node = NULL;
    uint8 gchip = 0;
    uint16 tid = 0;

    MALLOC_ZERO(MEM_LINKAGG_MODULE, wb_linkagg_group, sizeof(sys_wb_linkagg_group_t));
    CTC_ERROR_RETURN(NULL == wb_linkagg_group ? CTC_E_NO_MEMORY: CTC_E_NONE);

    MALLOC_ZERO(MEM_LINKAGG_MODULE, wb_linkagg_member, sizeof(sys_wb_linkagg_member_t));
    CTC_ERROR_RETURN(NULL == wb_linkagg_member ? CTC_E_NO_MEMORY: CTC_E_NONE);

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    LINKAGG_LOCK;

    /*restore linkagg master*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_linkagg_master_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER);
    sal_memset(&wb_linkagg_master, 0, sizeof(sys_wb_linkagg_master_t));
    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);
    if (wb_query.valid_cnt != 1 || wb_query.is_end != 1)
    {
        CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "query linkagg master error! valid_cnt: %d, is_end: %d.\n", wb_query.valid_cnt, wb_query.is_end);
        ret = CTC_E_NONE;
        goto done;
    }
    sal_memcpy((uint8 *)&wb_linkagg_master, (uint8 *)wb_query.buffer, wb_query.key_len + wb_query.data_len);
    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_LINKAGG, wb_linkagg_master.version))
    {
        CTC_ERROR_GOTO(CTC_E_VERSION_MISMATCH, ret, done);
    }
    if (p_usw_linkagg_master[lchip]->linkagg_mode != wb_linkagg_master.linkagg_mode)
    {
        CTC_ERROR_GOTO(CTC_E_VERSION_MISMATCH, ret, done);
    }

    p_usw_linkagg_master[lchip]->tx_load_percent = wb_linkagg_master.tx_load_percent;

    /*restore linkagg group*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_linkagg_group_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP);
    entry_cnt = 0;
    sal_memset(wb_linkagg_group, 0, sizeof(sys_wb_linkagg_group_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8 *)wb_linkagg_group, (uint8 *)wb_query.buffer + entry_cnt * (wb_query.key_len + wb_query.data_len), (wb_query.key_len + wb_query.data_len));
        entry_cnt++;
        p_linkagg = mem_malloc(MEM_LINKAGG_MODULE, sizeof(sys_linkagg_t));
        if (NULL == p_linkagg)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_linkagg, 0, sizeof(sys_linkagg_t));
        ret = _sys_usw_linkagg_wb_mapping_group(lchip, wb_linkagg_group, p_linkagg, 0, 0);
        if (ret)
        {
            mem_free(p_linkagg);
            continue;
        }
        tid = p_linkagg->tid;
        if (CTC_FLAG_ISSET(p_linkagg->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && DRV_IS_TSINGMA(lchip))
        {
            tid = (p_linkagg->tid >= MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM))?(p_linkagg->tid-MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)):(p_linkagg->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
        }
        else if (DRV_FROM_TMM(lchip) && CTC_FLAG_ISSET(p_linkagg->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH) && (CTC_MAX_UINT16_VALUE == p_linkagg->member_base))
        {
            tid = p_linkagg->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM);
        }
        ctc_vector_add(p_usw_linkagg_master[lchip]->group_vector, tid, p_linkagg);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*restore linkagg channel group*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_linkagg_group_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP);
    entry_cnt = 0;
    sal_memset(wb_linkagg_group, 0, sizeof(sys_wb_linkagg_group_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8 *)wb_linkagg_group, (uint8 *)wb_query.buffer + entry_cnt * (wb_query.key_len + wb_query.data_len), (wb_query.key_len + wb_query.data_len));
        entry_cnt++;
        p_linkagg = mem_malloc(MEM_LINKAGG_MODULE,  sizeof(sys_linkagg_t));
        if (NULL == p_linkagg)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_linkagg, 0, sizeof(sys_linkagg_t));
        ret = _sys_usw_linkagg_wb_mapping_group(lchip, wb_linkagg_group, p_linkagg, 0, 1);
        if (ret)
        {
            mem_free(p_linkagg);
            continue;
        }
        /*add to soft table*/
        ctc_vector_add(p_usw_linkagg_master[lchip]->chan_group, p_linkagg->tid, p_linkagg);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*restore linkagg member */
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_linkagg_member_t, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER);
    entry_cnt = 0;
    sal_memset(wb_linkagg_member, 0, sizeof(sys_wb_linkagg_member_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8 *)wb_linkagg_member, (uint8 *)wb_query.buffer + entry_cnt * (wb_query.key_len + wb_query.data_len), (wb_query.key_len + wb_query.data_len));
        entry_cnt++;

        if (wb_linkagg_member->is_channel_grp)
        {
            p_linkagg = ctc_vector_get(p_usw_linkagg_master[lchip]->chan_group, wb_linkagg_member->tid);
        }
        else
        {
            p_linkagg = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, wb_linkagg_member->tid);
        }
        if (!p_linkagg)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Group not Exist!\n");
            ret =  CTC_E_NOT_EXIST;
            goto done;
        }
        port_node = mem_malloc(MEM_LINKAGG_MODULE,  sizeof(sys_linkagg_port_t));
        if (!port_node)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret =   CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(port_node, 0, sizeof(sys_linkagg_port_t));
        p_linkagg->port_list[p_linkagg->port_cnt] = port_node;
        p_linkagg->port_list[p_linkagg->port_cnt]->is_local = wb_linkagg_member->valid;
        p_linkagg->port_list[p_linkagg->port_cnt]->nonuc_block_en = wb_linkagg_member->nonuc_block_en;
        p_linkagg->port_list[p_linkagg->port_cnt++]->gport = wb_linkagg_member->gport;
        gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(wb_linkagg_member->gport);
        if (TRUE == sys_usw_chip_is_local(lchip, gchip))
        {
            p_linkagg->local_port_cnt++;
        }

        /* restore xfabric type */
        /*
        if (p_usw_linkagg_master[lchip]->xfabric_en && 1 == entry_cnt)
        {
            CTC_ERROR_GOTO(sys_usw_port_api_get_property(lchip, wb_linkagg_member->gport, CTC_PORT_PROP_XFABRIC_TYPE, (uint32*)(&(p_linkagg->xfabric_type))), ret, done);
        }
        */
    CTC_WB_QUERY_ENTRY_END((&wb_query));

done:
    if (wb_query.key)
    {
        mem_free(wb_query.key);
    }
    CTC_WB_FREE_BUFFER(wb_query.buffer);
    mem_free(wb_linkagg_member);
    mem_free(wb_linkagg_group);
    LINKAGG_UNLOCK;

    return ret;
}

int32
_sys_usw_linkagg_wb_init(uint8 lchip)
{
   ctc_wb_appid_t  appid;
   sal_memset(&appid,0,sizeof(appid));

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER) ;
   appid.entry_num = 1;
   appid.entry_size  = sizeof(sys_wb_linkagg_master_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP) ;
   appid.entry_num = MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM)*2;
   appid.entry_size  = sizeof(sys_wb_linkagg_group_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_CHANGROUP) ;
   appid.entry_num = MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX);
   appid.entry_size  = sizeof(sys_wb_linkagg_group_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER) ;
   appid.entry_num = MCHIP_CAP(SYS_CAP_LINKAGG_ALL_MEM_NUM)*2;
   appid.entry_size  = sizeof(sys_wb_linkagg_member_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   return 0;
}

int32
_sys_usw_dump_linkagg_group_info(void* node_data, void* user_data)
{
    sys_linkagg_t *p_group = (sys_linkagg_t *)node_data;
    sal_file_t dump_db_fp = ((sys_dump_db_traverse_param_t*)user_data)->value0;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = ((sys_dump_db_traverse_param_t*)user_data)->lchip;
#endif
    SYS_DUMP_DB_LOG(dump_db_fp, "%-10u%-10u%-10u%-10u%-10u%-10u%-10u%-10u%-10u%-10u%-10u\n", p_group->tid, p_group->mode, p_group->member_base, p_group->max_member_num,
        p_group->real_member_num, p_group->ref_cnt, p_group->local_port_cnt, p_group->lsh_mode, ((p_group->flag & 
        CTC_LINKAGG_GROUP_FLAG_LOCAL_MEMBER_FIRST)?0:1), p_group->port_cnt, p_group->is_lag);
    return CTC_E_NONE;
}


int32
sys_usw_linkagg_dump_db(uint8 lchip, sal_file_t dump_db_fp,ctc_global_dump_db_t* p_dump_param)
{
    int32 ret = CTC_E_NONE;

    LINKAGG_LOCK;

    SYS_DUMP_DB_LOG(dump_db_fp, "\n");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "##Linkagg");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "{");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "---------------------------------------------------");
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","bind_gport_disable",p_usw_linkagg_master[lchip]->bind_gport_disable);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","linkagg_mode",p_usw_linkagg_master[lchip]->linkagg_mode);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","linkagg_num",MCHIP_CAP(SYS_CAP_SPEC_LINKAGG_GROUP_NUM));
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","chanagg_grp_num",MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX) - 1);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","chanagg_mem_per_grp",MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_PER_GRP_MEM));
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","opf_type",p_usw_linkagg_master[lchip]->opf_type);
    if(DRV_FROM_TM(lchip))
    {
        SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","rr_profile_bmp",p_usw_linkagg_master[lchip]->rr_profile_bmp);
    }
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","dlb_ewma_load_percent",p_usw_linkagg_master[lchip]->tx_load_percent);
    sys_usw_opf_fprint_alloc_used_info(lchip, p_usw_linkagg_master[lchip]->opf_type, dump_db_fp);
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "---------------------------------------------------");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "}");

    if(p_dump_param->detail)
    {
        sys_dump_db_traverse_param_t user_data;
        user_data.lchip = lchip;
        user_data.value0 = dump_db_fp;
        SYS_DUMP_DB_LOG(dump_db_fp, "linkagg group\n");
        SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "----------------------------------------------------------------------------------------------------------------");
        SYS_DUMP_DB_LOG(dump_db_fp, "%-10s%-10s%-10s%-10s%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", "Group", "Mode", "Mem_base", "Max_mem", "Real_mem", "Ref_cnt", "Lport_cnt", "Lsh_mode", "Canl_lmpf", "Port_cnt", "Mlag_replaced");
        SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "----------------------------------------------------------------------------------------------------------------");
        ctc_vector_traverse(p_usw_linkagg_master[lchip]->group_vector, _sys_usw_dump_linkagg_group_info , &user_data);

    }

    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_get_member_with_hash(uint8 lchip, uint16 tid, uint16 hash_value, uint32 * member_port)
{
    int32 ret = CTC_E_NONE;
    DsLinkAggregateGroup_m ds_link_agg_group;
    DsLinkAggregateMember_m ds_link_agg_mem;
    uint32 cmd = 0;
    uint32 agg_base = 0;
    uint32 mem_num = 0;
 
    LINKAGG_LOCK;
    cmd = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &ds_link_agg_group),ret, roll_back_0);

    if(0 != GetDsLinkAggregateGroup(V, lbMode_f, &ds_link_agg_group)
       && (4 != GetDsLinkAggregateGroup(V, lbMode_f, &ds_link_agg_group)))
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "diag compute lb hash only support static linkagg!\n");
        ret = CTC_E_NOT_SUPPORT;
        goto roll_back_0;
    }
    agg_base = GetDsLinkAggregateGroup(V, linkAggMemBase_f, &ds_link_agg_group);
    mem_num = GetDsLinkAggregateGroup(V, linkAggMemNum_f, &ds_link_agg_group);
    if (0 == mem_num)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "static linkagg no member!\n");
        ret = CTC_E_NOT_SUPPORT;
        goto roll_back_0;
    }
    cmd = DRV_IOR(DsLinkAggregateMember_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, agg_base+(hash_value&0xFF) % mem_num, cmd, &ds_link_agg_mem),ret, roll_back_0);
    *member_port = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(GetDsLinkAggregateMember(V, destChipId_f, &ds_link_agg_mem),
                                                    GetDsLinkAggregateMember(V, destId_f, &ds_link_agg_mem));
roll_back_0:
    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_set_nonuc_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16 cnt)
{
    int32 ret = CTC_E_NONE;
    uint16 index = 0;
    uint16 loop = 0;
    sys_linkagg_t *p_group = NULL;
    sys_linkagg_t old_group;
    sys_linkagg_port_t *port_node = NULL;
    uint32 tmp = 0;
    uint8 is_nonuc_detach = 0;

    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);
    CTC_PTR_VALID_CHECK(p_gports);
    CTC_MAX_VALUE_CHECK(cnt, MCHIP_CAP(SYS_CAP_LINKAGG_MEM_NUM));
    /*check global port*/
    for(index = 0; index < cnt; index++)
    {
        SYS_GLOBAL_PORT_CHECK(p_gports[index]);
        if(CTC_IS_CPU_PORT(p_gports[index]) || CTC_IS_LINKAGG_PORT(p_gports[index]))
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "[agg]Invalid gport!\n");
            return CTC_E_INVALID_PARAM;
        }
    }

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x\n", tid);
    sal_memset(&old_group, 0, sizeof(old_group));

    LINKAGG_LOCK;
    /* check exist */
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(NULL == p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Has not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto error_proc;
    }
    is_nonuc_detach = CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_GROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MEMBER, 1);
    if (MCHIP_LAG(lchip)->replace_nonuc_ports && is_nonuc_detach)
    {
        p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
        if(NULL == p_group)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Has not Exist!\n");
            ret = CTC_E_NOT_EXIST;
            goto error_proc;
        }
        sal_memcpy(&old_group, p_group, sizeof(old_group));
        /*0. alloc new port_list*/
        p_group->local_port_cnt = 0;
        p_group->port_cnt = 0;
        p_group->port_list = mem_malloc(MEM_LINKAGG_MODULE, cnt * sizeof(void*));
        if((!p_group->port_list) && (0 != cnt))
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto error_proc;

        }
        sal_memset(p_group->port_list, 0, cnt * sizeof(void*));

        /*1. find the old member isn't linkagg member*/
        for(loop = 0; loop < old_group.port_cnt; loop++)
        {
            port_node = old_group.port_list[loop];
            if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(port_node->gport)))
            {
                port_node->valid  = 1;
            }
            for (index = 0; index < cnt; index++)
            {
                if (port_node->gport == p_gports[index])
                {
                    port_node->valid = 0;
                }
            }
        }

        /*2. add the nonuc ports to db*/
        for(loop = 0; loop < cnt; loop++)
        {
            CTC_ERROR_GOTO(_sys_usw_linkagg_add_port_to_db(lchip, p_group, p_gports[loop], 0, 0), ret, error_proc1);
        }

        /*3. update linkagg group nonucbitmap and nonucbitmapblock*/
        CTC_ERROR_GOTO(MCHIP_LAG(lchip)->replace_nonuc_ports(lchip, p_group), ret, error_proc1);

        /*4. update mcast linkagg bitmap and set global port*/
        for(loop = 0; loop < cnt; loop++)
        {
            tmp = p_gports[loop];
            if (sys_usw_chip_is_local(lchip, (SYS_MAP_CTC_GPORT_TO_GCHIP(tmp))))
            {
                sys_usw_port_api_update_mc_linkagg(lchip, tid, CTC_MAP_GPORT_TO_LPORT(tmp), TRUE);
            }
        }

        /*5. unset old nonuc port mcast linkagg bitmap and global port*/
        for(loop = 0; loop < old_group.port_cnt; loop++)
        {
            port_node = old_group.port_list[loop];
            if(port_node->valid && sys_usw_chip_is_local(lchip, (SYS_MAP_CTC_GPORT_TO_GCHIP(port_node->gport))))
            {
                sys_usw_port_api_update_mc_linkagg(lchip, tid, CTC_MAP_GPORT_TO_LPORT(port_node->gport), FALSE);
            }
        }

        /*6. free old group*/
        for (loop = 0; loop < old_group.port_cnt; loop++ )
        {
            mem_free(old_group.port_list[loop]);
        }
        mem_free(old_group.port_list);
    }
    else if (DRV_IS_TSINGMA(lchip) && is_nonuc_detach)
    {
        ret = _sys_usw_linkagg_replace_ports(lchip, tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM), p_gports, cnt, 0);
    }
    else if (MCHIP_LAG(lchip)->replace_nonuc_ports)
    {
        uint8 is_find = 0;
        for(loop = 0; loop < p_group->port_cnt; loop++)
        {
            port_node = p_group->port_list[loop];
            if (NULL == port_node)
            {
                continue;
            }
            is_find = 0;
            for(index = 0; index < cnt; index++)
            {
                if (port_node->gport == p_gports[index])
                {
                    is_find = 1;
                    break;
                }
            }

            /*1. nonuc port must blong to linkagg member ports, if not ignore*/
            if (0 == is_find)
            {
                port_node->nonuc_block_en = 1;
                continue;
            }
            port_node->nonuc_block_en = 0;
        }
        ret = MCHIP_LAG(lchip)->replace_nonuc_ports(lchip, p_group);
    }
    else
    {
        ret = CTC_E_NOT_SUPPORT;
    }

    LINKAGG_UNLOCK;

    return ret;
  
error_proc1:
    for(index = 0; index < loop; index++)
    {
        _sys_usw_linkagg_remove_port_to_db(lchip, p_group, p_gports[index]);
    }
    mem_free(p_group->port_list);
    sal_memcpy(p_group, &old_group, sizeof(old_group));
error_proc:
    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_get_nonuc_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16* p_cnt)
{
    int32 ret = CTC_E_NONE;
    sys_linkagg_t *p_group = NULL;
    sys_linkagg_port_t *port_node = NULL;
    uint16 count = 0;
    uint16 loop = 0;

    SYS_LINKAGG_INIT_CHECK();
    SYS_TID_VALID_CHECK(tid);
    CTC_PTR_VALID_CHECK(p_gports);
    CTC_PTR_VALID_CHECK(p_cnt);

    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "tid = 0x%x\n", tid);

    LINKAGG_LOCK;
    /* check exist */
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(NULL == p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Has Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto error_proc;
    }
    if (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
    {
        p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
        if (NULL == p_group)
        {
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Has Exist!\n");
            ret = CTC_E_NOT_EXIST;
            goto error_proc;
        }
    }

    for(loop = 0; loop < p_group->port_cnt; loop++)
    {
        port_node = p_group->port_list[loop];
        if (NULL == port_node)
        {
            continue;
        }
        if (0 == port_node->nonuc_block_en)
        {
            p_gports[count] = p_group->port_list[loop]->gport;
            count++;
        }
    }
    *p_cnt = count;

error_proc:
    LINKAGG_UNLOCK;

    return ret;
}

int32
sys_usw_linkagg_set_rr_en(uint8 lchip, uint16 tid, uint8 rr_en, uint8 is_random)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint8 rr_profile_id = 0;
    DsLinkAggregateRrCount_m ds_linkagg_rr;
    LagRrProfileIdMappingCtl_m lag_rrprofile;
    DsLinkAggregateGroup_m ds_linkagg_group;
    sys_linkagg_t* p_group = NULL;
    SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_LINKAGG_INIT_CHECK();
    sal_memset(&ds_linkagg_rr, 0, sizeof(ds_linkagg_rr));
    sal_memset(&lag_rrprofile, 0, sizeof(lag_rrprofile));

    LINKAGG_LOCK;
    /* check exist */
    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if(!p_group)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Linkagg Not Exist!\n");
        ret = CTC_E_NOT_EXIST;
        goto error_proc;
    }
    if ((p_group->mode != CTC_LINKAGG_MODE_STATIC && rr_en) || (p_group->mode == CTC_LINKAGG_MODE_STATIC && !rr_en))
    {
        ret = CTC_E_INVALID_CONFIG;
        goto error_proc;
    }
    rr_profile_id = _sys_usw_linkagg_find_rr_profile_id(lchip, tid);

    if (rr_profile_id >= SYS_LINKAGG_RR_COUNT_MAX)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Linkagg] rr mod is invalid,because it greater than 15 \n");
        ret = CTC_E_NO_RESOURCE;
        goto error_proc;
    }

    /* 1. prepare profile */
    if (rr_en)
    {
        SetDsLinkAggregateRrCount(V, randomRrEn_f, &ds_linkagg_rr, is_random?1:0);
        cmd = DRV_IOW(DsLinkAggregateRrCount_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, rr_profile_id, cmd, &ds_linkagg_rr), ret, error_proc);
        
        CTC_BIT_SET(p_usw_linkagg_master[lchip]->rr_profile_bmp, rr_profile_id);
        SetLagRrProfileIdMappingCtl(V, rrProfileId_f, &lag_rrprofile, rr_profile_id);
        cmd = DRV_IOW(LagRrProfileIdMappingCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &lag_rrprofile), ret, error_proc);
    }
    else
    {
        cmd = DRV_IOR(LagRrProfileIdMappingCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &lag_rrprofile), ret, error_proc);
        rr_profile_id = GetLagRrProfileIdMappingCtl(V, rrProfileId_f, &lag_rrprofile);
        CTC_BIT_UNSET(p_usw_linkagg_master[lchip]->rr_profile_bmp, rr_profile_id);
    }
    /* 2. modify to rr mode and assign RrCount profile or modify to static mode*/
    cmd = DRV_IOR(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &ds_linkagg_group), ret, error_proc);
    SetDsLinkAggregateGroup(V, lbMode_f, &ds_linkagg_group, rr_en?2:0);
    cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, tid, cmd, &ds_linkagg_group), ret, error_proc);

    /*3. modify the soft table*/
    p_group->mode = rr_en? CTC_LINKAGG_MODE_RR : CTC_LINKAGG_MODE_STATIC;
    if (is_random)
    {
        p_group->flag |= CTC_LINKAGG_GROUP_FLAG_RANDOM_RR;
    }
    else
    {
        p_group->flag &= ~CTC_LINKAGG_GROUP_FLAG_RANDOM_RR;
    }

error_proc:
    LINKAGG_UNLOCK;
    return ret;
}

